Merge pull request #1481 from corda/chrisr3-os-merf

Merge from Open Source up to 47068e6b7
This commit is contained in:
Chris Rankin 2018-10-16 13:55:44 +01:00 committed by GitHub
commit a5d93703f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 668 additions and 154 deletions

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=4.0.29
gradlePluginsVersion=4.0.32
kotlinVersion=1.2.51
# ***************************************************************#
# When incrementing platformVersion make sure to update #

View File

@ -198,11 +198,23 @@ CorDapps can advertise their minimum and target platform version. The minimum pl
.. sourcecode:: groovy
'Min-Platform-Version': 3
'Min-Platform-Version': 4
'Target-Platform-Version': 4
Using the `cordapp` Gradle plugin, this can be achieved by putting this in your CorDapp's `build.gradle`:
In gradle, this can be achieved by modifying the jar task as shown in this example:
.. container:: codeset
.. sourcecode:: groovy
cordapp {
info {
targetPlatformVersion 4
minimumPlatformVersion 4
}
}
Without using the `cordapp` plugin, you can achieve the same by modifying the jar task as shown in this example:
.. container:: codeset
@ -211,7 +223,7 @@ In gradle, this can be achieved by modifying the jar task as shown in this examp
jar {
manifest {
attributes(
'Min-Platform-Version': 3
'Min-Platform-Version': 4
'Target-Platform-Version': 4
)
}

View File

@ -0,0 +1,346 @@
.. raw:: html
<style> .red {color:red} </style>
.. role:: red
Deterministic Corda Modules
===========================
A Corda contract's verify function should always produce the same results for the same input data. To that end,
Corda provides the following modules:
#. ``core-deterministic``
#. ``serialization-deterministic``
#. ``jdk8u-deterministic``
These are reduced version of Corda's ``core`` and ``serialization`` modules and the OpenJDK 8 ``rt.jar``, where the
non-deterministic functionality has been removed. The intention here is that all CorDapp classes required for
contract verification should be compiled against these modules to prevent them containing non-deterministic behaviour.
.. note:: These modules are only a development aid. They cannot guarantee determinism without also including
deterministic versions of all their dependent libraries, e.g. ``kotlin-stdlib``.
Generating the Deterministic Modules
------------------------------------
JDK 8
``jdk8u-deterministic`` is a "pseudo JDK" image that we can point the Java and Kotlin compilers to. It downloads the
``rt.jar`` containing a deterministic subset of the Java 8 APIs from the Artifactory.
To build a new version of this JAR and upload it to the Artifactory, see the ``create-jdk8u`` module. This is a
standalone Gradle project within the Corda repository that will clone the ``deterministic-jvm8`` branch of Corda's
`OpenJDK repository <https://github.com/corda/openjdk>`_ and then build it. (This currently requires a C++ compiler,
GNU Make and a UNIX-like development environment.)
Corda Modules
``core-deterministic`` and ``serialization-deterministic`` are generated from Corda's ``core`` and ``serialization``
modules respectively using both `ProGuard <https://www.guardsquare.com/en/proguard>`_ and Corda's ``JarFilter`` Gradle
plugin. Corda developers configure these tools by applying Corda's ``@KeepForDJVM`` and ``@DeleteForDJVM``
annotations to elements of ``core`` and ``serialization`` as described :ref:`here <deterministic_annotations>`.
The build generates each of Corda's deterministic JARs in six steps:
#. Some *very few* classes in the original JAR must be replaced completely. This is typically because the original
class uses something like ``ThreadLocal``, which is not available in the deterministic Java APIs, and yet the
class is still required by the deterministic JAR. We must keep such classes to a minimum!
#. The patched JAR is analysed by ProGuard for the first time using the following rule:
.. sourcecode:: groovy
keep '@interface net.corda.core.KeepForDJVM { *; }'
..
ProGuard works by calculating how much code is reachable from given "entry points", and in our case these entry
points are the ``@KeepForDJVM`` classes. The unreachable classes are then discarded by ProGuard's ``shrink``
option.
#. The remaining classes may still contain non-deterministic code. However, there is no way of writing a ProGuard rule
explicitly to discard anything. Consider the following class:
.. sourcecode:: kotlin
@CordaSerializable
@KeepForDJVM
data class UniqueIdentifier @JvmOverloads @DeleteForDJVM constructor(
val externalId: String? = null,
val id: UUID = UUID.randomUUID()
) : Comparable<UniqueIdentifier> {
...
}
..
While CorDapps will definitely need to handle ``UniqueIdentifier`` objects, all of the secondary constructors
generate a new random ``UUID`` and so are non-deterministic. Hence the next "determinising" step is to pass the
classes to the ``JarFilter`` tool, which strips out all of the elements which have been annotated as
``@DeleteForDJVM`` and stubs out any functions annotated with ``@StubOutForDJVM``. (Stub functions that
return a value will throw ``UnsupportedOperationException``, whereas ``void`` or ``Unit`` stubs will do nothing.)
#. After the ``@DeleteForDJVM`` elements have been filtered out, the classes are rescanned using ProGuard to remove
any more code that has now become unreachable.
#. The remaining classes define our deterministic subset. However, the ``@kotlin.Metadata`` annotations on the compiled
Kotlin classes still contain references to all of the functions and properties that ProGuard has deleted. Therefore
we now use the ``JarFilter`` to delete these references, as otherwise the Kotlin compiler will pretend that the
deleted functions and properties are still present.
#. Finally, we use ProGuard again to validate our JAR against the deterministic ``rt.jar``:
.. literalinclude:: ../../core-deterministic/build.gradle
:language: groovy
:start-after: DOCSTART 01
:end-before: DOCEND 01
..
This step will fail if ProGuard spots any Java API references that still cannot be satisfied by the deterministic
``rt.jar``, and hence it will break the build.
Configuring IntelliJ with a Deterministic SDK
---------------------------------------------
We would like to configure IntelliJ so that it will highlight uses of non-deterministic Java APIs as :red:`not found`.
Or, more specifically, we would like IntelliJ to use the ``deterministic-rt.jar`` as a "Module SDK" for deterministic
modules rather than the ``rt.jar`` from the default project SDK, to make IntelliJ consistent with Gradle.
This is possible, but slightly tricky to configure because IntelliJ will not recognise an SDK containing only the
``deterministic-rt.jar`` as being valid. It also requires that IntelliJ delegate all build tasks to Gradle, and that
Gradle be configured to use the Project's SDK.
Creating the Deterministic SDK
Gradle creates a suitable JDK image in the project's ``jdk8u-deterministic/jdk`` directory, and you can
configure IntelliJ to use this location for this SDK. However, you should also be aware that IntelliJ SDKs
are available for *all* projects to use.
To create this JDK image, execute the following:
.. code-block:: bash
$ gradlew jdk8u-deterministic:copyJdk
..
Now select ``File/Project Structure/Platform Settings/SDKs`` and add a new JDK SDK with the
``jdk8u-deterministic/jdk`` directory as its home. Rename this SDK to something like "1.8 (Deterministic)".
This *should* be sufficient for IntelliJ. However, if IntelliJ realises that this SDK does not contain a
full JDK then you will need to configure the new SDK by hand:
#. Create a JDK Home directory with the following contents:
``jre/lib/rt.jar``
where ``rt.jar`` here is this renamed artifact:
.. code-block:: xml
<dependency>
<groupId>net.corda</groupId>
<artifactId>deterministic-rt</artifactId>
<classifier>api</classifier>
</dependency>
..
#. While IntelliJ is *not* running, locate the ``config/options/jdk.table.xml`` file in IntelliJ's configuration
directory. Add an empty ``<jdk>`` section to this file:
.. code-block:: xml
<jdk version="2">
<name value="1.8 (Deterministic)"/>
<type value="JavaSDK"/>
<version value="java version &quot;1.8.0&quot;"/>
<homePath value=".. path to the deterministic JDK directory .."/>
<roots>
</roots>
</jdk>
..
#. Open IntelliJ and select ``File/Project Structure/Platform Settings/SDKs``. The "1.8 (Deterministic)" SDK
should now be present. Select it and then click on the ``Classpath`` tab. Press the "Add" / "Plus" button to
add ``rt.jar`` to the SDK's classpath. Then select the ``Annotations`` tab and include the same JAR(s) as
the other SDKs.
Configuring the Corda Project
#. Open the root ``build.gradle`` file and define this property:
.. code-block:: gradle
buildscript {
ext {
...
deterministic_idea_sdk = '1.8 (Deterministic)'
...
}
}
..
Configuring IntelliJ
#. Go to ``File/Settings/Build, Execution, Deployment/Build Tools/Gradle``, and configure Gradle's JVM to be the
project's JVM.
#. Go to ``File/Settings/Build, Execution, Deployment/Build Tools/Gradle/Runner``, and select these options:
- Delegate IDE build/run action to Gradle
- Run tests using the Gradle Test Runner
#. Delete all of the ``out`` directories that IntelliJ has previously generated for each module.
#. Go to ``View/Tool Windows/Gradle`` and click the ``Refresh all Gradle projects`` button.
These steps will enable IntelliJ's presentation compiler to use the deterministic ``rt.jar`` with the following modules:
- ``core-deterministic``
- ``serialization-deterministic``
- ``core-deterministic:testing:common``
but still build everything using Gradle with the full JDK.
Testing the Deterministic Modules
---------------------------------
The ``core-deterministic:testing`` module executes some basic JUnit tests for the ``core-deterministic`` and
``serialization-deterministic`` JARs. These tests are compiled against the deterministic ``rt.jar``, although
they are still executed using the full JDK.
The ``testing`` module also has two sub-modules:
``core-deterministic:testing:data``
This module generates test data such as serialised transactions and elliptic curve key pairs using the full
non-deterministic ``core`` library and JDK. This data is all written into a single JAR which the ``testing``
module adds to its classpath.
``core-deterministic:testing:common``
This module provides the test classes which the ``testing`` and ``data`` modules need to share. It is therefore
compiled against the deterministic API subset.
.. _deterministic_annotations:
Applying @KeepForDJVM and @DeleteForDJVM annotations
----------------------------------------------------
Corda developers need to understand how to annotate classes in the ``core`` and ``serialization`` modules correctly
in order to maintain the deterministic JARs.
.. note:: Every Kotlin class still has its own ``.class`` file, even when all of those classes share the same
source file. Also, annotating the file:
.. sourcecode:: kotlin
@file:KeepForDJVM
package net.corda.core.internal
..
*does not* automatically annotate any class declared *within* this file. It merely annotates any
accompanying Kotlin ``xxxKt`` class.
For more information about how ``JarFilter`` is processing the byte-code inside ``core`` and ``serialization``,
use Gradle's ``--info`` or ``--debug`` command-line options.
Deterministic Classes
Classes that *must* be included in the deterministic JAR should be annotated as ``@KeepForDJVM``.
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/KeepForDJVM.kt
:language: kotlin
:start-after: DOCSTART 01
:end-before: DOCEND 01
..
To preserve any Kotlin functions, properties or type aliases that have been declared outside of a ``class``,
you should annotate the source file's ``package`` declaration instead:
.. sourcecode:: kotlin
@file:JvmName("InternalUtils")
@file:KeepForDJVM
package net.corda.core.internal
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
..
Non-Deterministic Elements
Elements that *must* be deleted from classes in the deterministic JAR should be annotated as ``@DeleteForDJVM``.
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/DeleteForDJVM.kt
:language: kotlin
:start-after: DOCSTART 01
:end-before: DOCEND 01
..
You must also ensure that a deterministic class's primary constructor does not reference any classes that are
not available in the deterministic ``rt.jar``. The biggest risk here would be that ``JarFilter`` would delete the
primary constructor and that the class could no longer be instantiated, although ``JarFilter`` will print a warning
in this case. However, it is also likely that the "determinised" class would have a different serialisation
signature than its non-deterministic version and so become unserialisable on the deterministic JVM.
Primary constructors that have non-deterministic default parameter values must still be annotated as
``@DeleteForDJVM`` because they cannot be refactored without breaking Corda's binary interface. The Kotlin compiler
will automatically apply this ``@DeleteForDJVM`` annotation - along with any others - to all of the class's
secondary constructors too. The ``JarFilter`` plugin can then remove the ``@DeleteForDJVM`` annotation from the
primary constructor so that it can subsequently delete only the secondary constructors.
The annotations that ``JarFilter`` will "sanitise" from primary constructors in this way are listed in the plugin's
configuration block, e.g.
.. sourcecode:: groovy
task jarFilter(type: JarFilterTask) {
...
annotations {
...
forSanitise = [
"net.corda.core.DeleteForDJVM"
]
}
}
..
Be aware that package-scoped Kotlin properties are all initialised within a common ``<clinit>`` block inside
their host ``.class`` file. This means that when ``JarFilter`` deletes these properties, it cannot also remove
their initialisation code. For example:
.. sourcecode:: kotlin
package net.corda.core
@DeleteForDJVM
val map: MutableMap<String, String> = ConcurrentHashMap()
..
In this case, ``JarFilter`` would delete the ``map`` property but the ``<clinit>`` block would still create
an instance of ``ConcurrentHashMap``. The solution here is to refactor the property into its own file and then
annotate the file itself as ``@DeleteForDJVM`` instead.
Non-Deterministic Function Stubs
Sometimes it is impossible to delete a function entirely. Or a function may have some non-deterministic code
embedded inside it that cannot be removed. For these rare cases, there is the ``@StubOutForDJVM``
annotation:
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/StubOutForDJVM.kt
:language: kotlin
:start-after: DOCSTART 01
:end-before: DOCEND 01
..
This annotation instructs ``JarFilter`` to replace the function's body with either an empty body (for functions
that return ``void`` or ``Unit``) or one that throws ``UnsupportedOperationException``. For example:
.. sourcecode:: kotlin
fun necessaryCode() {
nonDeterministicOperations()
otherOperations()
}
@StubOutForDJVM
private fun nonDeterministicOperations() {
// etc
}
..

View File

@ -84,6 +84,10 @@ application development please continue to refer to `the main project documentat
json.rst
deterministic-modules.rst
troubleshooting.rst
design/reference-states/design.md
design/threat-model/corda-threat-model.md
design/data-model-upgrades/signature-constraints.md
design/data-model-upgrades/package-namespace-ownership.md
.. conditional-toctree::
:caption: Operations
@ -91,5 +95,4 @@ application development please continue to refer to `the main project documentat
:if_tag: htmlmode
corda-nodes-index.rst
corda-networks-index.rst
certificate-revocation
corda-networks-index.rstcertificate-revocation

View File

@ -61,10 +61,20 @@ jar {
'Implementation-Version': rootProject.version
)
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
cordapp {
info {
name "net/corda/experimental/ha-testing"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -33,3 +33,13 @@ idea {
publish {
name 'corda-notary-bft-smart'
}
cordapp {
info {
name "net/corda/experimental/notary-bft-smart"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -33,3 +33,12 @@ idea {
publish {
name 'corda-notary-raft'
}
cordapp {
info {
name "net/corda/experimental/notary-raft"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -55,10 +55,20 @@ jar {
'Implementation-Version': rootProject.version
)
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
cordapp {
info {
name "net/corda/experimental/rpc-worker"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -87,6 +87,8 @@ cordapp {
info {
name "net/corda/finance"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -1,10 +1,9 @@
package net.corda.finance.compat
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.messaging.startFlow
import net.corda.core.utilities.getOrThrow
import net.corda.finance.flows.CashException
import net.corda.finance.flows.test.CashExceptionThrowingFlow
import net.corda.node.services.Permissions.Companion.all
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
@ -41,10 +40,3 @@ class CashExceptionSerialisationTest : IntegrationTest() {
}
}
}
@StartableByRPC
class CashExceptionThrowingFlow : FlowLogic<Unit>() {
override fun call() {
throw CashException("BOOM!", IllegalStateException("Nope dude!"))
}
}

View File

@ -1,4 +1,4 @@
package net.corda.finance.flows
package net.corda.finance.flows.test
import net.corda.core.messaging.startFlow
import net.corda.core.utilities.getOrThrow
@ -8,6 +8,7 @@ import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.finance.flows.CashConfigDataFlow
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.driver
import net.corda.testing.internal.IntegrationTest
@ -26,7 +27,9 @@ class CashConfigDataFlowTest : IntegrationTest() {
}
@Test
fun `issuable currencies are read in from node config`() {
driver(DriverParameters(notarySpecs = emptyList())) {
driver(DriverParameters(
extraCordappPackagesToScan = listOf("net.corda.finance.flows"),
notarySpecs = emptyList())) {
val node = startNode(customOverrides = mapOf("custom" to mapOf("issuableCurrencies" to listOf("EUR", "USD")))).getOrThrow()
val config = node.rpc.startFlow(::CashConfigDataFlow).returnValue.getOrThrow()
assertThat(config.issuableCurrencies).containsExactly(EUR, USD)

View File

@ -1,4 +1,4 @@
package net.corda.finance.contracts.asset
package net.corda.finance.contracts.asset.test
import net.corda.core.contracts.*
import net.corda.core.crypto.toStringShort
@ -8,9 +8,10 @@ import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.QueryableState
import net.corda.core.transactions.LedgerTransaction
import net.corda.finance.schemas.SampleCashSchemaV1
import net.corda.finance.schemas.SampleCashSchemaV2
import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.contracts.asset.OnLedgerAsset
import net.corda.finance.schemas.test.SampleCashSchemaV1
import net.corda.finance.schemas.test.SampleCashSchemaV2
import net.corda.finance.schemas.test.SampleCashSchemaV3
import net.corda.finance.utils.sumCash
import net.corda.finance.utils.sumCashOrNull
import net.corda.finance.utils.sumCashOrZero
@ -18,7 +19,7 @@ import java.security.PublicKey
import java.util.*
class DummyFungibleContract : OnLedgerAsset<Currency, DummyFungibleContract.Commands, DummyFungibleContract.State>() {
override fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): List<CommandWithParties<DummyFungibleContract.Commands>>
override fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): List<CommandWithParties<Commands>>
= commands.select()
data class State(

View File

@ -0,0 +1,12 @@
package net.corda.finance.flows.test
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.finance.flows.CashException
@StartableByRPC
class CashExceptionThrowingFlow : FlowLogic<Unit>() {
override fun call() {
throw CashException("BOOM!", IllegalStateException("Nope dude!"))
}
}

View File

@ -1,4 +1,4 @@
package net.corda.finance.schemas
package net.corda.finance.schemas.test
import net.corda.core.contracts.MAX_ISSUER_REF_SIZE
import net.corda.core.schemas.MappedSchema

View File

@ -1,4 +1,4 @@
package net.corda.finance.schemas
package net.corda.finance.schemas.test
import net.corda.core.identity.AbstractParty
import net.corda.core.schemas.CommonSchemaV1

View File

@ -1,4 +1,4 @@
package net.corda.finance.schemas
package net.corda.finance.schemas.test
import net.corda.core.contracts.MAX_ISSUER_REF_SIZE
import net.corda.core.identity.AbstractParty

View File

@ -1,4 +1,4 @@
package net.corda.finance.schemas
package net.corda.finance.schemas.test
import net.corda.core.contracts.MAX_ISSUER_REF_SIZE
import net.corda.core.schemas.MappedSchema

View File

@ -1,4 +1,4 @@
package net.corda.finance.schemas
package net.corda.finance.schemas.test
import net.corda.core.contracts.MAX_ISSUER_REF_SIZE
import net.corda.core.identity.AbstractParty

View File

@ -79,7 +79,7 @@ dependencies {
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
runtime "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
runtimeOnly "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"

View File

@ -18,8 +18,8 @@ import net.corda.core.node.services.vault.QueryCriteria.VaultCustomQueryCriteria
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria;
import net.corda.finance.contracts.DealState;
import net.corda.finance.contracts.asset.Cash;
import net.corda.finance.schemas.SampleCashSchemaV2;
import net.corda.finance.schemas.CashSchemaV1;
import net.corda.finance.schemas.test.SampleCashSchemaV2;
import net.corda.node.services.api.IdentityServiceInternal;
import net.corda.nodeapi.internal.persistence.CordaPersistence;
import net.corda.nodeapi.internal.persistence.DatabaseTransaction;

View File

@ -23,11 +23,11 @@ import net.corda.finance.DOLLARS
import net.corda.finance.POUNDS
import net.corda.finance.SWISS_FRANCS
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.DummyFungibleContract
import net.corda.finance.contracts.asset.test.DummyFungibleContract
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.schemas.SampleCashSchemaV1
import net.corda.finance.schemas.SampleCashSchemaV2
import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.schemas.test.SampleCashSchemaV1
import net.corda.finance.schemas.test.SampleCashSchemaV2
import net.corda.finance.schemas.test.SampleCashSchemaV3
import net.corda.finance.utils.sumCash
import net.corda.node.internal.configureDatabase
import net.corda.node.services.api.IdentityServiceInternal

View File

@ -6,8 +6,7 @@ import net.corda.core.node.services.vault.*
import net.corda.core.node.services.vault.QueryCriteria.*
import net.corda.finance.*
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.schemas.test.SampleCashSchemaV3
import net.corda.testing.core.*
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions.assertThatThrownBy

View File

@ -22,8 +22,8 @@ import net.corda.finance.contracts.asset.cash.selection.AbstractCashSelection
import net.corda.finance.schemas.CashSchemaV1
import net.corda.finance.schemas.CashSchemaV1.PersistentCashState
import net.corda.finance.schemas.CommercialPaperSchemaV1
import net.corda.finance.schemas.SampleCashSchemaV2
import net.corda.finance.schemas.SampleCashSchemaV3
import net.corda.finance.schemas.test.SampleCashSchemaV2
import net.corda.finance.schemas.test.SampleCashSchemaV3
import net.corda.node.internal.configureDatabase
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig

View File

@ -25,3 +25,12 @@ idea {
publish {
name 'corda-notary-jpa'
}
cordapp {
info {
name "net/corda/notary/jpa"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -27,3 +27,12 @@ idea {
publish {
name 'corda-notary-mysql'
}
cordapp {
info {
name "net/corda/notary/mysql"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -34,8 +34,6 @@ task integrationTest(type: Test) {
}
dependencies {
// Note the :finance module is a CorDapp in its own right
// and CorDapps using :finance features should use 'cordapp' not 'compile' linkage.
cordaCompile project(':core')
cordaCompile project(':confidential-identities')
@ -70,6 +68,15 @@ jar {
baseName 'corda-ptflows'
}
cordapp {
info {
name "net/corda/perftestcordapp"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}
publish {
name jar.baseName
}

View File

@ -1,11 +1,8 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'maven-publish'
sourceSets {
integrationTest {
@ -27,14 +24,16 @@ dependencies {
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':webserver')
cordaCompile project(':node-driver')
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, webTask]) {
ext.rpcUsers = [['username': "demo", 'password': "demo", 'permissions': ["StartFlow.net.corda.attachmentdemo.AttachmentDemoFlow",
"InvokeRpc.wellKnownPartyFromX500Name",
"InvokeRpc.attachmentExists",
@ -92,18 +91,6 @@ idea {
}
}
publishing {
publications {
jarAndSources(MavenPublication) {
from components.java
artifactId 'attachmentdemo'
artifact sourceJar
artifact javadocJar
}
}
}
task runSender(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'net.corda.attachmentdemo.AttachmentDemoKt'
@ -125,3 +112,12 @@ jar {
)
}
}
cordapp {
info {
name "net/corda/samples/attachment-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -2,10 +2,8 @@ apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'maven-publish'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@ -14,8 +12,8 @@ dependencies {
cordapp project(':finance')
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':client:jfx')
cordaCompile project(':client:rpc')
@ -32,7 +30,9 @@ dependencies {
testCompile "junit:junit:$junit_version"
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, webTask]) {
nodeDefaults {
cordapp project(':finance')
}
@ -82,18 +82,6 @@ idea {
}
}
publishing {
publications {
jarAndSources(MavenPublication) {
from components.java
artifactId 'bankofcorda'
artifact sourceJar
artifact javadocJar
}
}
}
task runRPCCashIssue(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'net.corda.bank.IssueCash'
@ -123,3 +111,12 @@ jar {
)
}
}
cordapp {
info {
name "net/corda/samples/bank-of-corda-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -1,11 +1,7 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'maven-publish'
sourceSets {
integrationTest {
@ -17,7 +13,7 @@ sourceSets {
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
cordaCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// For CSV parsing.
compile "com.opencsv:opencsv:4.0"
@ -46,4 +42,14 @@ jar {
'Automatic-Module-Name': 'net.corda.samples.demos.businessnetwork'
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
cordapp {
info {
name "net/corda/samples/business-network-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -1,17 +1,20 @@
apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
dependencies {
cordaCompile project(":core")
cordaCompile project(":node-api")
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':node-api')
runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
// Corda integration dependencies
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, webTask]) {
directory file("$buildDir/nodes")
nodeDefaults {
cordapps = []
@ -25,7 +28,6 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
port 10003
adminPort 10004
}
rpcUsers = []
extraConfig = ['h2Settings.address' : 'localhost:10005']
}
node {
@ -54,4 +56,13 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
}
extraConfig = ['h2Settings.address' : 'localhost:10013']
}
}
}
cordapp {
info {
name "net/corda/samples/cordapp-configuration"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -1,8 +1,14 @@
package net.corda.configsample
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.utilities.ProgressTracker
@StartableByRPC
@ -17,3 +23,22 @@ class GetStringConfigFlow(private val configKey: String) : FlowLogic<String>() {
return config.getString(configKey)
}
}
@CordaSerializable
data class GetStringTestState(val responses: List<String>, val issuer: AbstractParty) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(issuer)
}
@CordaSerializable
object GetStringTestCommand : CommandData
class GetStringTestContract : Contract {
override fun verify(tx: LedgerTransaction) {
}
}

View File

@ -21,7 +21,6 @@ ext['jackson.version'] = "$jackson_version"
ext['dropwizard-metrics.version'] = "$metrics_version"
ext['mockito.version'] = "$mockito_version"
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

View File

@ -1,11 +1,8 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'maven-publish'
apply plugin: 'application'
mainClassName = 'net.corda.irs.IRSDemo'
@ -31,7 +28,7 @@ dependencies {
cordapp project(':finance')
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
// Cordapp dependencies
@ -57,7 +54,8 @@ def rpcUsersList = [
]]
]
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask]) {
node {
name "O=Notary Service,L=Zurich,C=CH"
@ -112,7 +110,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
}
task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar']) {
task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar', nodeTask]) {
node {
name "O=Notary Service,L=Zurich,C=CH"
@ -159,15 +157,25 @@ tasks.withType(CreateStartScripts).each { task ->
idea {
module {
downloadJavadoc = true // defaults to false
downloadJavadoc = true
downloadSources = true
}
}
jar {
from sourceSets.test.output
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
artifacts {
demoArtifacts jar
}
}
cordapp {
info {
name "net/corda/irs-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -1,18 +1,20 @@
apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
dependencies {
cordaCompile project(":core")
cordaCompile project(":node-api")
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':node-api')
testCompile project(":test-utils")
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask]) {
ext.rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]]
directory "./build/nodes"
@ -48,4 +50,13 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
}
extraConfig = ['h2Settings.address' : 'localhost:0']
}
}
}
cordapp {
info {
name "net/corda/samples/network-verifier"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -16,8 +16,8 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':client:jfx')
cordaCompile project(':client:rpc')
@ -28,9 +28,12 @@ dependencies {
cordapp project(':experimental:notary-bft-smart')
}
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(dependsOn: ['deployNodesSingle', 'deployNodesRaft', 'deployNodesBFT', 'deployNodesCustom'])
task deployNodesSingle(type: Cordform, dependsOn: 'jar') {
task deployNodesSingle(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
directory file("$buildDir/nodes/nodesSingle")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
@ -55,7 +58,7 @@ task deployNodesSingle(type: Cordform, dependsOn: 'jar') {
}
}
task deployNodesCustom(type: Cordform, dependsOn: 'jar') {
task deployNodesCustom(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
directory file("$buildDir/nodes/nodesCustom")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
@ -83,7 +86,7 @@ task deployNodesCustom(type: Cordform, dependsOn: 'jar') {
}
}
task deployNodesRaft(type: Cordform, dependsOn: 'jar') {
task deployNodesRaft(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
def className = "net.corda.notary.raft.RaftNotaryService"
directory file("$buildDir/nodes/nodesRaft")
nodeDefaults {
@ -151,7 +154,7 @@ task deployNodesRaft(type: Cordform, dependsOn: 'jar') {
}
}
task deployNodesBFT(type: Cordform, dependsOn: 'jar') {
task deployNodesBFT(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
def clusterAddresses = ["localhost:11000", "localhost:11010", "localhost:11020", "localhost:11030"]
def className = "net.corda.notary.bftsmart.BftSmartNotaryService"
directory file("$buildDir/nodes/nodesBFT")
@ -250,3 +253,12 @@ jar {
)
}
}
cordapp {
info {
name "net/corda/samples/notary-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -4,7 +4,6 @@ allprojects {
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
@ -40,7 +39,7 @@ configurations {
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
cordaCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
// The SIMM demo CorDapp depends upon Cash CorDapp features
cordapp project(':finance')
@ -76,7 +75,9 @@ dependencies {
testCompile "org.assertj:assertj-core:$assertj_version"
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, webTask]) {
directory file("$buildDir/nodes")
nodeDefaults {
cordapp project(':finance')
@ -84,6 +85,9 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
cordapp project(':samples:simm-valuation-demo:flows')
rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]]
}
signing {
enabled false
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
@ -155,4 +159,11 @@ task integrationTest(type: Test, dependsOn: []) {
task scenarioJar(type: Jar, dependsOn: classes) {
classifier "behave-test"
from sourceSets.scenario.output
}
cordapp {
info {
vendor = 'R3'
targetPlatformVersion = corda_platform_version.toInteger()
}
}

View File

@ -6,6 +6,12 @@ def shrinkJar = file("$buildDir/libs/${project.name}-${project.version}-tiny.jar
cordapp {
info {
vendor = 'R3'
targetPlatformVersion = corda_platform_version.toInteger()
}
signing {
// We need to sign the output of the "shrink" task,
// but the jar signer doesn't support that yet.
enabled false
}
}

View File

@ -4,6 +4,10 @@ apply plugin: 'net.corda.plugins.cordapp'
cordapp {
info {
vendor = 'R3'
targetPlatformVersion = corda_platform_version.toInteger()
}
signing {
enabled false
}
}

View File

@ -1,11 +1,8 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'maven-publish'
sourceSets {
integrationTest {
@ -29,8 +26,8 @@ dependencies {
cordapp project(':finance')
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
// Corda Plugins: dependent flows and services
@ -41,7 +38,9 @@ dependencies {
testCompile "org.assertj:assertj-core:${assertj_version}"
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
def nodeTask = tasks.getByPath(':node:capsule:assemble')
def webTask = tasks.getByPath(':webserver:webcapsule:assemble')
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, webTask]) {
ext.rpcUsers = [['username': "demo", 'password': "demo", 'permissions': ["ALL"]]]
directory "./build/nodes"
@ -104,18 +103,6 @@ idea {
}
}
publishing {
publications {
jarAndSources(MavenPublication) {
from components.java
artifactId 'traderdemo'
artifact sourceJar
artifact javadocJar
}
}
}
task runBank(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'net.corda.traderdemo.TraderDemoKt'
@ -136,4 +123,13 @@ jar {
'Automatic-Module-Name': 'net.corda.samples.demos.trader'
)
}
}
}
cordapp {
info {
name "net/corda/samples/trader-demo"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -29,7 +29,6 @@ sourceSets {
dependencies {
compile project(':test-utils')
compile "net.corda.plugins:cordform-common:$gradle_plugins_version"
// Integration test helpers
testCompile "org.assertj:assertj-core:$assertj_version"

View File

@ -18,6 +18,8 @@ cordapp {
info {
vendor "R3"
version corda_release_version
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -15,10 +15,7 @@ sourceSets {
}
dependencies {
cordaCompile(project(":node")) { // Not node-api so we get metrics.
// The Node only needs this for binary compatibility with Cordapps written in Kotlin 1.1.
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jre8'
}
cordaCompile project(":node") // Not node-api so we get metrics.
cordapp project(":tools:notary-healthcheck:contract")
testCompile project(":node-driver")
}
@ -32,6 +29,8 @@ cordapp {
info {
vendor "R3"
version corda_release_version
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}

View File

@ -2,16 +2,15 @@ import net.corda.plugins.Cordform
apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
cordaCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testCompile "junit:junit:$junit_version"
// Corda integration dependencies
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core')
cordaCompile project(':client:rpc')
cordaCompile project(':node-driver')
@ -28,20 +27,9 @@ idea {
}
}
publishing {
publications {
jarAndSources(MavenPublication) {
from components.java
artifactId 'notarytest'
artifact sourceJar
artifact javadocJar
}
}
}
task deployJDBC(type: Cordform, dependsOn: 'jar') {
definitionClass = 'net.corda.notarytest.JDBCNotaryCordform'
def nodeTask = tasks.getByPath(':node:capsule:assemble')
task deployJDBC(type: Cordform, dependsOn: ['jar', nodeTask]) {
// Nodes require porting from net.corda.notarytest.JDBCNotaryCordform
}
task runTest(type: JavaExec) {
@ -55,4 +43,14 @@ jar {
'Automatic-Module-Name': 'net.corda.notarytest'
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
cordapp {
info {
name "net/corda/notarytest"
vendor "R3"
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion 1
}
}