From 9cdda3bd7722d91f7ea54ad724ef86fe4c2a9217 Mon Sep 17 00:00:00 2001 From: josecoll Date: Fri, 14 Dec 2018 09:39:23 +0000 Subject: [PATCH] CORDA-2149 CorDapp Contract and Workflow version identifiers (#4363) * Implementation of Contract and Workflow attribute identifiers. * Fixes following rebase from master. * Fix broken JUnit test. * Fix broken JUnit test. * Fix broken JUnit test. * Added missing constants. * Further clean-up. * Updated documentation. * Added changelog entry. * Updated all samples (using new Gradle Plugin 4.0.37 functionality) * Temporarily resolve gradle plugins from latest published snapshot. * Temporarily resolve gradle plugins from latest published snapshot. * Updates following feedback from PR review. * Move constants into CordappInfo companion object. * Contract and Workflow attribute `version` to `versionId` (as version is a reserved gradle variable) * Clarified warning message on incorrect version identifier. * Align version identifier processing logic with gradle cordapp plugin. * Updated comment. * Minor fixes following rebase from master. * Fixed broken unit test. * Improved exception reporting. * Update to use 4.0.37 of Gradle Plugins. * Added support for combined Contract and Workflow CorDapp info. * Updated following discussions with Shams + cleanup. * Updated following Shams PR review. * Minor API improvements. * Added missing cordapp info causing deployNodes to fail. --- constants.properties | 2 +- .../core/contracts/ContractAttachment.kt | 2 +- .../net/corda/core/cordapp/ConfigException.kt | 7 +- .../kotlin/net/corda/core/cordapp/Cordapp.kt | 65 ++++++++++++++ .../net/corda/core/cordapp/CordappInfo.kt | 5 -- .../core/internal/cordapp/CordappImpl.kt | 49 ++++++++--- .../internal/cordapp/CordappInfoResolver.kt | 14 +-- .../core/internal/cordapp/ManifestUtils.kt | 86 ++++++++++++++++++ .../rules/TargetVersionDependentRules.kt | 8 +- .../internal/AttachmentsClassLoader.kt | 10 +-- .../core/transactions/LedgerTransaction.kt | 2 +- .../core/transactions/TransactionBuilder.kt | 2 +- .../core/transactions/WireTransaction.kt | 3 +- .../net/corda/core/flows/AttachmentTests.kt | 11 ++- .../cordapp/CordappInfoResolverTest.kt | 7 +- .../transactions/TransactionBuilderTest.kt | 2 +- docs/source/changelog.rst | 7 ++ docs/source/cordapp-build-systems.rst | 88 ++++++++++++++++--- experimental/notary-bft-smart/build.gradle | 11 +-- experimental/notary-raft/build.gradle | 10 ++- finance/build.gradle | 34 +++---- ...tachmentsClassLoaderStaticContractTests.kt | 2 +- .../SignatureConstraintVersioningTests.kt | 4 +- .../net/corda/node/internal/NodeStartup.kt | 4 +- .../cordapp/JarScanningCordappLoader.kt | 4 +- .../node/internal/cordapp/ManifestUtils.kt | 53 ----------- .../node/internal/cordapp/VirtualCordapps.kt | 5 +- .../persistence/NodeAttachmentService.kt | 8 +- .../persistence/NodeAttachmentServiceTest.kt | 10 +-- samples/attachment-demo/build.gradle | 10 ++- samples/bank-of-corda-demo/build.gradle | 10 ++- samples/cordapp-configuration/build.gradle | 10 ++- samples/irs-demo/cordapp/build.gradle | 18 ++-- samples/network-verifier/build.gradle | 10 ++- samples/notary-demo/build.gradle | 10 ++- samples/simm-valuation-demo/build.gradle | 15 +++- .../contracts-states/build.gradle | 12 ++- .../simm-valuation-demo/flows/build.gradle | 12 ++- samples/trader-demo/build.gradle | 10 ++- .../net/corda/testing/node/TestCordapp.kt | 9 +- .../testing/node/internal/TestCordappImpl.kt | 3 - .../node/internal/TestCordappsUtils.kt | 30 ++++++- .../node/internal/TestCordappsUtilsTest.kt | 10 ++- .../core/internal/ContractJarTestUtils.kt | 15 ++-- .../testing/internal/InternalTestUtils.kt | 2 +- .../testing/internal/MockCordappProvider.kt | 3 +- .../testing/services/MockAttachmentStorage.kt | 2 +- 47 files changed, 475 insertions(+), 231 deletions(-) delete mode 100644 core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt create mode 100644 core/src/main/kotlin/net/corda/core/internal/cordapp/ManifestUtils.kt delete mode 100644 node/src/main/kotlin/net/corda/node/internal/cordapp/ManifestUtils.kt diff --git a/constants.properties b/constants.properties index f3223f4c44..cfdf79b05d 100644 --- a/constants.properties +++ b/constants.properties @@ -1,4 +1,4 @@ -gradlePluginsVersion=4.0.36 +gradlePluginsVersion=4.0.37 kotlinVersion=1.2.71 # ***************************************************************# # When incrementing platformVersion make sure to update # diff --git a/core/src/main/kotlin/net/corda/core/contracts/ContractAttachment.kt b/core/src/main/kotlin/net/corda/core/contracts/ContractAttachment.kt index b227826995..29d893a3ed 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/ContractAttachment.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/ContractAttachment.kt @@ -1,8 +1,8 @@ package net.corda.core.contracts import net.corda.core.KeepForDJVM +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.serialization.CordaSerializable -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import java.security.PublicKey /** diff --git a/core/src/main/kotlin/net/corda/core/cordapp/ConfigException.kt b/core/src/main/kotlin/net/corda/core/cordapp/ConfigException.kt index affbce62dd..e1b5064aa5 100644 --- a/core/src/main/kotlin/net/corda/core/cordapp/ConfigException.kt +++ b/core/src/main/kotlin/net/corda/core/cordapp/ConfigException.kt @@ -3,4 +3,9 @@ package net.corda.core.cordapp /** * Thrown if an exception occurs in accessing or parsing cordapp configuration */ -class CordappConfigException(msg: String, e: Throwable) : Exception(msg, e) \ No newline at end of file +class CordappConfigException(msg: String, e: Throwable) : Exception(msg, e) + +/** + * Thrown if an exception occurs whilst parsing version identifiers within cordapp configuration + */ +class CordappInvalidVersionException(msg: String) : Exception(msg) \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/cordapp/Cordapp.kt b/core/src/main/kotlin/net/corda/core/cordapp/Cordapp.kt index ddf369b668..a4dc38ee68 100644 --- a/core/src/main/kotlin/net/corda/core/cordapp/Cordapp.kt +++ b/core/src/main/kotlin/net/corda/core/cordapp/Cordapp.kt @@ -4,6 +4,10 @@ import net.corda.core.DeleteForDJVM import net.corda.core.DoNotImplement import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogic +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN_VALUE +import net.corda.core.internal.cordapp.CordappImpl.Companion.parseVersion import net.corda.core.schemas.MappedSchema import net.corda.core.serialization.SerializationCustomSerializer import net.corda.core.serialization.SerializationWhitelist @@ -47,5 +51,66 @@ interface Cordapp { val allFlows: List>> val jarPath: URL val cordappClasses: List + val info: Info val jarHash: SecureHash.SHA256 + + /** + * CorDapp's information, including vendor and version. + * + * @property shortName Cordapp's shortName + * @property vendor Cordapp's vendor + * @property version Cordapp's version + */ + @DoNotImplement + interface Info { + val shortName: String + val vendor: String + val version: String + val licence: String + val minimumPlatformVersion: Int + val targetPlatformVersion: Int + + fun hasUnknownFields(): Boolean + + /** CorDapps that do not separate Contracts and Flows into separate jars (pre Corda 4) */ + data class Default(override val shortName: String, override val vendor: String, override val version: String, override val minimumPlatformVersion: Int, override val targetPlatformVersion: Int, override val licence: String = UNKNOWN_VALUE) + : Info { + override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, version).any { it == UNKNOWN_VALUE } + override fun toString() = "CorDapp $shortName version $version by $vendor with licence $licence" + } + + /** A Contract CorDapp contains contract definitions (state, commands) and verification logic */ + data class Contract(override val shortName: String, override val vendor: String, val versionId: Int, override val licence: String, override val minimumPlatformVersion: Int, override val targetPlatformVersion: Int) + : Info { + override val version: String + get() = versionId.toString() + override fun toString() = "Contract CorDapp: $shortName version $version by vendor $vendor with licence $licence" + override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, licence).any { it == UNKNOWN_VALUE } + } + + /** A Workflow CorDapp contains flows and services used to implement business transactions using contracts and states persisted to the immutable ledger */ + data class Workflow(override val shortName: String, override val vendor: String, val versionId: Int, override val licence: String, override val minimumPlatformVersion: Int, override val targetPlatformVersion: Int) + : Info { + override val version: String + get() = versionId.toString() + override fun toString() = "Workflow CorDapp: $shortName version $version by vendor $vendor with licence $licence" + override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, licence).any { it == UNKNOWN_VALUE } + } + + /** A CorDapp that includes both Contract and Workflow classes (not recommended) */ + // TODO: future work in Gradle cordapp plugins to enforce separation of Contract and Workflow classes into separate jars + data class ContractAndWorkflow(val contract: Contract, val workflow: Workflow, override val minimumPlatformVersion: Int, override val targetPlatformVersion: Int) + : Info { + override val shortName: String + get() = "Contract: ${contract.shortName}, Workflow: ${workflow.shortName}" + override val vendor: String + get() = "Contract: ${contract.vendor}, Workflow: ${workflow.vendor}" + override val licence: String + get() = "Contract: ${contract.licence}, Workflow: ${workflow.licence}" + override val version: String + get() = "Contract: ${contract.versionId}, Workflow: ${workflow.versionId}" + override fun toString() = "Combined CorDapp: $contract, $workflow" + override fun hasUnknownFields(): Boolean = contract.hasUnknownFields() || workflow.hasUnknownFields() + } + } } diff --git a/core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt b/core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt deleted file mode 100644 index 9981f0b444..0000000000 --- a/core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.corda.core.cordapp - -const val CORDAPP_CONTRACT_VERSION = "Implementation-Version" //TODO will be changed to "Corda-Contract-Version" - -const val DEFAULT_CORDAPP_VERSION: Int = 1 \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappImpl.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappImpl.kt index afcaeb0af9..9b9e073b01 100644 --- a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappImpl.kt +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappImpl.kt @@ -2,6 +2,7 @@ package net.corda.core.internal.cordapp import net.corda.core.DeleteForDJVM import net.corda.core.cordapp.Cordapp +import net.corda.core.cordapp.CordappInvalidVersionException import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogic import net.corda.core.internal.notary.NotaryService @@ -25,7 +26,7 @@ data class CordappImpl( override val customSchemas: Set, override val allFlows: List>>, override val jarPath: URL, - val info: Info, + override val info: Cordapp.Info, override val jarHash: SecureHash.SHA256, val notaryService: Class?, /** Indicates whether the CorDapp is loaded from external sources, or generated on node startup (virtual). */ @@ -34,8 +35,42 @@ data class CordappImpl( companion object { fun jarName(url: URL): String = url.toPath().fileName.toString().removeSuffix(".jar") - } + /** CorDapp manifest entries */ + const val CORDAPP_CONTRACT_NAME = "Cordapp-Contract-Name" + const val CORDAPP_CONTRACT_VERSION = "Cordapp-Contract-Version" + const val CORDAPP_CONTRACT_VENDOR = "Cordapp-Contract-Vendor" + const val CORDAPP_CONTRACT_LICENCE = "Cordapp-Contract-Licence" + + const val CORDAPP_WORKFLOW_NAME = "Cordapp-Workflow-Name" + const val CORDAPP_WORKFLOW_VERSION = "Cordapp-Workflow-Version" + const val CORDAPP_WORKFLOW_VENDOR = "Cordapp-Workflow-Vendor" + const val CORDAPP_WORKFLOW_LICENCE = "Cordapp-Workflow-Licence" + + const val TARGET_PLATFORM_VERSION = "Target-Platform-Version" + const val MIN_PLATFORM_VERSION = "Min-Platform-Version" + + const val UNKNOWN_VALUE = "Unknown" + const val DEFAULT_CORDAPP_VERSION = 1 + + /** used for CorDapps that do not explicitly define attributes */ + val UNKNOWN = Cordapp.Info.Default(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE,1, 1) + + /** Helper method for version identifier parsing */ + fun parseVersion(versionStr: String?, attributeName: String): Int { + if (versionStr == null) + throw CordappInvalidVersionException("Target versionId attribute $attributeName not specified. Please specify a whole number starting from 1.") + return try { + val version = versionStr.toInt() + if (version < 1) { + throw CordappInvalidVersionException("Target versionId ($versionStr) for attribute $attributeName must not be smaller than 1.") + } + return version + } catch (e: NumberFormatException) { + throw CordappInvalidVersionException("Version identifier ($versionStr) for attribute $attributeName must be a whole number starting from 1.") + } + } + } /** * An exhaustive list of all classes relevant to the node within this CorDapp * @@ -45,14 +80,4 @@ data class CordappImpl( val classList = rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass } + notaryService classList.mapNotNull { it?.name } + contractClassNames } - - // TODO Why a seperate Info class and not just have the fields directly in CordappImpl? - data class Info(val shortName: String, val vendor: String, val version: String, val minimumPlatformVersion: Int, val targetPlatformVersion: Int) { - companion object { - const val UNKNOWN_VALUE = "Unknown" - val UNKNOWN = Info(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE, 1, 1) - } - - fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, version).any { it == UNKNOWN_VALUE } - } } \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt index 8a2253d062..257d22e37d 100644 --- a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt @@ -1,5 +1,6 @@ package net.corda.core.internal.cordapp +import net.corda.core.cordapp.Cordapp import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.VisibleForTesting import net.corda.core.utilities.loggerFor @@ -10,10 +11,10 @@ import java.util.concurrent.ConcurrentHashMap */ object CordappInfoResolver { private val logger = loggerFor() - private val cordappClasses: ConcurrentHashMap> = ConcurrentHashMap() + private val cordappClasses: ConcurrentHashMap> = ConcurrentHashMap() // TODO Use the StackWalker API once we migrate to Java 9+ - private var cordappInfoResolver: () -> CordappImpl.Info? = { + private var cordappInfoResolver: () -> Cordapp.Info? = { Exception().stackTrace .mapNotNull { cordappClasses[it.className] } // If there is more than one cordapp registered for a class name we can't determine the "correct" one and return null. @@ -25,7 +26,7 @@ object CordappInfoResolver { * This could happen when trying to run different versions of the same CorDapp on the same node. */ @Synchronized - fun register(classes: List, cordapp: CordappImpl.Info) { + fun register(classes: List, cordapp: Cordapp.Info) { classes.forEach { if (cordappClasses.containsKey(it)) { logger.warn("More than one CorDapp registered for $it.") @@ -45,7 +46,7 @@ object CordappInfoResolver { * @return Information about the CorDapp from which the invoker is called, null if called outside a CorDapp or the * calling CorDapp cannot be reliably determined. */ - val currentCordappInfo: CordappImpl.Info? get() = cordappInfoResolver() + val currentCordappInfo: Cordapp.Info? get() = cordappInfoResolver() /** * Returns the target version of the current calling CorDapp. Defaults to the current platform version if there isn't one. @@ -60,12 +61,13 @@ object CordappInfoResolver { @VisibleForTesting fun withCordappInfo(shortName: String = "CordappInfoResolver.withCordappInfo", vendor: String = "Corda", - version: String = "1.0", + version: String = "1", + licence: String = "Apache", minimumPlatformVersion: Int = 1, targetPlatformVersion: Int = PLATFORM_VERSION, block: () -> T): T { val currentResolver = cordappInfoResolver - cordappInfoResolver = { CordappImpl.Info(shortName, vendor, version, minimumPlatformVersion, targetPlatformVersion) } + cordappInfoResolver = { Cordapp.Info.Default(shortName, vendor, version, minimumPlatformVersion, targetPlatformVersion, licence) } try { return block() } finally { diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/ManifestUtils.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/ManifestUtils.kt new file mode 100644 index 0000000000..13a280c38c --- /dev/null +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/ManifestUtils.kt @@ -0,0 +1,86 @@ +package net.corda.core.internal.cordapp + +import net.corda.core.cordapp.Cordapp +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_LICENCE +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VENDOR +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_LICENCE +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_VENDOR +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.MIN_PLATFORM_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.TARGET_PLATFORM_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN_VALUE +import net.corda.core.internal.cordapp.CordappImpl.Companion.parseVersion +import java.util.jar.Attributes +import java.util.jar.Manifest + +operator fun Manifest.set(key: String, value: String): String? { + return mainAttributes.putValue(key, value) +} + +operator fun Manifest.set(key: Attributes.Name, value: String): Any? { + return mainAttributes.put(key, value) +} + +operator fun Manifest.get(key: String): String? = mainAttributes.getValue(key) + +val Manifest.targetPlatformVersion: Int + get() { + val minPlatformVersion = this[MIN_PLATFORM_VERSION]?.toIntOrNull() ?: 1 + return this[TARGET_PLATFORM_VERSION]?.toIntOrNull() ?: minPlatformVersion + } + +fun Manifest.toCordappInfo(defaultName: String): Cordapp.Info { + + /** Common attributes */ + val minPlatformVersion = this[MIN_PLATFORM_VERSION]?.toIntOrNull() ?: 1 + val targetPlatformVersion = this[TARGET_PLATFORM_VERSION]?.toIntOrNull() ?: minPlatformVersion + + /** new identifiers (Corda 4) */ + // is it a Contract Jar? + val contractInfo = + if (this[CORDAPP_CONTRACT_NAME] != null) { + Cordapp.Info.Contract(shortName = this[CORDAPP_CONTRACT_NAME] ?: defaultName, + vendor = this[CORDAPP_CONTRACT_VENDOR] ?: UNKNOWN_VALUE, + versionId = parseVersion(this[CORDAPP_CONTRACT_VERSION], CORDAPP_CONTRACT_VERSION), + licence = this[CORDAPP_CONTRACT_LICENCE] ?: UNKNOWN_VALUE, + minimumPlatformVersion = minPlatformVersion, + targetPlatformVersion = targetPlatformVersion + ) + } else null + + // is it a Workflow (flows and services) Jar? + val workflowInfo = + if (this[CORDAPP_WORKFLOW_NAME] != null) { + Cordapp.Info.Workflow(shortName = this[CORDAPP_WORKFLOW_NAME] ?: defaultName, + vendor = this[CORDAPP_WORKFLOW_VENDOR] ?: UNKNOWN_VALUE, + versionId = parseVersion(this[CORDAPP_WORKFLOW_VERSION],CORDAPP_WORKFLOW_VERSION), + licence = this[CORDAPP_WORKFLOW_LICENCE] ?: UNKNOWN_VALUE, + minimumPlatformVersion = minPlatformVersion, + targetPlatformVersion = targetPlatformVersion + ) + } else null + + // combined Contract and Workflow Jar ? + if (contractInfo != null && workflowInfo != null) { + return Cordapp.Info.ContractAndWorkflow(contractInfo, workflowInfo, minPlatformVersion, targetPlatformVersion) + } + else if (contractInfo != null) return contractInfo + else if (workflowInfo != null) return workflowInfo + + /** need to maintain backwards compatibility so use old identifiers if existent */ + val shortName = this["Name"] ?: defaultName + val vendor = this["Implementation-Vendor"] ?: UNKNOWN_VALUE + val version = this["Implementation-Version"] ?: UNKNOWN_VALUE + return Cordapp.Info.Default( + shortName = shortName, + vendor = vendor, + version = version, + licence = UNKNOWN_VALUE, + minimumPlatformVersion = minPlatformVersion, + targetPlatformVersion = targetPlatformVersion + ) +} + diff --git a/core/src/main/kotlin/net/corda/core/internal/rules/TargetVersionDependentRules.kt b/core/src/main/kotlin/net/corda/core/internal/rules/TargetVersionDependentRules.kt index 5cb3cc5ada..c0fffdd551 100644 --- a/core/src/main/kotlin/net/corda/core/internal/rules/TargetVersionDependentRules.kt +++ b/core/src/main/kotlin/net/corda/core/internal/rules/TargetVersionDependentRules.kt @@ -1,13 +1,12 @@ package net.corda.core.internal.rules import net.corda.core.contracts.ContractState -import net.corda.core.utilities.contextLogger +import net.corda.core.internal.cordapp.targetPlatformVersion import net.corda.core.utilities.warnOnce import org.slf4j.LoggerFactory import java.net.URL import java.util.concurrent.ConcurrentHashMap import java.util.jar.JarInputStream -import java.util.jar.Manifest // This file provides rules that depend on the targetVersion of the current Contract or Flow. // Rules defined in this package are automatically removed from the DJVM in core-deterministic, @@ -47,9 +46,4 @@ object StateContractValidationEnforcementRule { return targetVersion >= 4 } -} - -private val Manifest.targetPlatformVersion: Int get() { - val minPlatformVersion = mainAttributes.getValue("Min-Platform-Version")?.toInt() ?: 1 - return mainAttributes.getValue("Target-Platform-Version")?.toInt() ?: minPlatformVersion } \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/serialization/internal/AttachmentsClassLoader.kt b/core/src/main/kotlin/net/corda/core/serialization/internal/AttachmentsClassLoader.kt index f3d185a786..3eb67da42d 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/internal/AttachmentsClassLoader.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/internal/AttachmentsClassLoader.kt @@ -6,6 +6,7 @@ import net.corda.core.contracts.TransactionVerificationException.OverlappingAtta import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 import net.corda.core.internal.VisibleForTesting +import net.corda.core.internal.cordapp.targetPlatformVersion import net.corda.core.internal.createSimpleCache import net.corda.core.internal.isUploaderTrusted import net.corda.core.internal.toSynchronised @@ -18,7 +19,6 @@ import java.io.ByteArrayOutputStream import java.io.IOException import java.io.InputStream import java.net.* -import java.util.jar.Manifest /** * A custom ClassLoader that knows how to load classes from a set of attachments. The attachments themselves only @@ -108,14 +108,6 @@ class AttachmentsClassLoader(attachments: List, parent: ClassLoader } } - // This was reused from: https://github.com/corda/corda/pull/4240. - // TODO - Once that is merged it should be extracted to a utility. - private val Manifest.targetPlatformVersion: Int - get() { - val minPlatformVersion = mainAttributes.getValue("Min-Platform-Version")?.toInt() ?: 1 - return mainAttributes.getValue("Target-Platform-Version")?.toInt() ?: minPlatformVersion - } - @VisibleForTesting private fun readAttachment(attachment: Attachment, filepath: String): ByteArray { ByteArrayOutputStream().use { diff --git a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt index b197dde0ec..6bb6dbe290 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt @@ -6,11 +6,11 @@ import net.corda.core.contracts.* import net.corda.core.contracts.TransactionVerificationException.TransactionContractConflictException import net.corda.core.contracts.TransactionVerificationException.TransactionRequiredContractUnspecifiedException import net.corda.core.contracts.Version -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.SecureHash import net.corda.core.crypto.isFulfilledBy import net.corda.core.identity.Party import net.corda.core.internal.* +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.rules.StateContractValidationEnforcementRule import net.corda.core.internal.uncheckedCast import net.corda.core.node.NetworkParameters diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index e099965716..fb2378d1a4 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -4,11 +4,11 @@ import co.paralleluniverse.strands.Strand import net.corda.core.CordaInternal import net.corda.core.DeleteForDJVM import net.corda.core.contracts.* -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.contracts.ContractAttachment.Companion.getContractVersion import net.corda.core.crypto.* import net.corda.core.identity.Party import net.corda.core.internal.* +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.node.NetworkParameters import net.corda.core.node.ServiceHub import net.corda.core.node.ServicesForResolution diff --git a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt index 5460a2274b..b4a88e0796 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt @@ -7,13 +7,12 @@ import net.corda.core.contracts.* import net.corda.core.contracts.ComponentGroupEnum.COMMANDS_GROUP import net.corda.core.contracts.ComponentGroupEnum.OUTPUTS_GROUP import net.corda.core.contracts.ContractAttachment.Companion.getContractVersion -import net.corda.core.contracts.Version -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.* import net.corda.core.identity.Party import net.corda.core.internal.AbstractAttachment import net.corda.core.internal.Emoji import net.corda.core.internal.SerializedStateAndRef +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.createComponentGroups import net.corda.core.node.NetworkParameters import net.corda.core.node.ServiceHub diff --git a/core/src/test/kotlin/net/corda/core/flows/AttachmentTests.kt b/core/src/test/kotlin/net/corda/core/flows/AttachmentTests.kt index 3181293264..8161426c4e 100644 --- a/core/src/test/kotlin/net/corda/core/flows/AttachmentTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/AttachmentTests.kt @@ -4,19 +4,22 @@ import co.paralleluniverse.fibers.Suspendable import com.natpryce.hamkrest.* import com.natpryce.hamkrest.assertion.assert import net.corda.core.contracts.Attachment -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.SecureHash -import net.corda.testing.internal.matchers.flow.willReturn -import net.corda.testing.internal.matchers.flow.willThrow import net.corda.core.flows.mixins.WithMockNet import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.internal.FetchAttachmentsFlow import net.corda.core.internal.FetchDataFlow +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.hash import net.corda.node.services.persistence.NodeAttachmentService -import net.corda.testing.core.* +import net.corda.testing.core.ALICE_NAME +import net.corda.testing.core.BOB_NAME +import net.corda.testing.core.makeUnique +import net.corda.testing.core.singleIdentity import net.corda.testing.internal.fakeAttachment +import net.corda.testing.internal.matchers.flow.willReturn +import net.corda.testing.internal.matchers.flow.willThrow import net.corda.testing.node.internal.InternalMockNetwork import net.corda.testing.node.internal.InternalMockNodeParameters import net.corda.testing.node.internal.TestStartedNode diff --git a/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt b/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt index 1a28785094..bdd24b7111 100644 --- a/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt +++ b/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt @@ -1,5 +1,6 @@ package net.corda.core.internal.cordapp +import net.corda.core.cordapp.Cordapp import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before @@ -17,7 +18,7 @@ class CordappInfoResolverTest { fun `the correct cordapp resolver is used after calling withCordappInfo`() { val defaultTargetVersion = 222 - CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test", "test", "2", 3, defaultTargetVersion)) + CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test", "test", "2", 3, defaultTargetVersion)) assertEquals(defaultTargetVersion, CordappInfoResolver.currentTargetVersion) val expectedTargetVersion = 555 @@ -30,8 +31,8 @@ class CordappInfoResolverTest { @Test fun `when more than one cordapp is registered for the same class, the resolver returns null`() { - CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test", "test", "2", 3, 222)) - CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test1", "test1", "1", 2, 456)) + CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test", "test", "2", 3, 222)) + CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test1", "test1", "1", 2, 456)) assertThat(CordappInfoResolver.currentCordappInfo).isNull() } } diff --git a/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt b/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt index cf808ae49e..c18e239985 100644 --- a/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt +++ b/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt @@ -4,7 +4,6 @@ import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.contracts.* import net.corda.core.cordapp.CordappProvider -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.SecureHash import net.corda.core.identity.Party @@ -12,6 +11,7 @@ import net.corda.core.internal.AbstractAttachment import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.RPC_UPLOADER +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.node.ServicesForResolution import net.corda.core.node.ZoneVersionTooLowException import net.corda.core.node.services.AttachmentStorage diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 1282a75c59..557c89e3ba 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -18,6 +18,13 @@ Unreleased For a given contract class, the contract attachment of the output states must be of the same or newer version than the contract attachment of the input states. See :ref:`Contract attachment non-downgrade rule ` for further information. +* Standardised CorDapp version identifiers in jar manifests (aligned with associated cordapp Gradle plugin changes). + Updated all samples to reflect new conventions. + +* Introduction of unique CorDapp version identifiers in jar manifests for contract and flows/services CorDapps. + Updated all sample CorDapps to reflect new conventions. + See :ref:`CorDapp separation ` for further information. + * Automatic Constraints propagation for hash-constrained states to signature-constrained states. This allows Corda 4 signed CorDapps using signature constraints to consume existing hash constrained states generated by unsigned CorDapps in previous versions of Corda. diff --git a/docs/source/cordapp-build-systems.rst b/docs/source/cordapp-build-systems.rst index 96e4e8a473..61975291c0 100644 --- a/docs/source/cordapp-build-systems.rst +++ b/docs/source/cordapp-build-systems.rst @@ -368,13 +368,20 @@ There is an example project that demonstrates in ``samples`` called ``cordapp-co Minimum and target platform version ----------------------------------- -CorDapps can advertise their minimum and target platform version. The minimum platform version indicates that a node has to run at least this version in order to be able to run this CorDapp. The target platform version indicates that a CorDapp was tested with this version of the Corda Platform and should be run at this API level if possible. It provides a means of maintaining behavioural compatibility for the cases where the platform's behaviour has changed. These attributes are specified in the JAR manifest of the CorDapp, for example: +CorDapps can advertise their minimum and target platform version. The minimum platform version indicates that a node has to run at least this +version in order to be able to run this CorDapp. The target platform version indicates that a CorDapp was tested with this version of the Corda +Platform and should be run at this API level if possible. It provides a means of maintaining behavioural compatibility for the cases where the +platform's behaviour has changed. These attributes are specified in the JAR manifest of the CorDapp, for example: .. sourcecode:: groovy 'Min-Platform-Version': 4 'Target-Platform-Version': 4 +**Defaults** + - ``Target-Platform-Version`` (mandatory) is a whole number and must comply with the rules mentioned above. + - ``Min-Platform-Version`` (optional) will default to 1 if not specified. + Using the `cordapp` Gradle plugin, this can be achieved by putting this in your CorDapp's `build.gradle`: .. container:: codeset @@ -382,23 +389,80 @@ Using the `cordapp` Gradle plugin, this can be achieved by putting this in your .. sourcecode:: groovy cordapp { - info { - targetPlatformVersion 4 - minimumPlatformVersion 4 - } + targetPlatformVersion 4 + minimumPlatformVersion 4 } -Without using the `cordapp` plugin, you can achieve the same by modifying the jar task as shown in this example: +.. _cordapp_separation_ref: + +Separation of CorDapp contracts, flows and services +--------------------------------------------------- +It is recommended that **contract** code (states, commands, verification logic) be packaged separately from **business flows** (and associated services). +This decoupling enables *contracts* to evolve independently from the *flows* and *services* that use them. Contracts may even be specified and implemented by different +providers (eg. Corda currently ships with a cash financial contract which in turn is used in many other flows and many other CorDapps). + +As of Corda 4, CorDapps can explicitly differentiate their type by specifying the following attributes in the JAR manifest: + +.. sourcecode:: groovy + + 'Cordapp-Contract-Name' + 'Cordapp-Contract-Version' + 'Cordapp-Contract-Vendor' + 'Cordapp-Contract-Licence' + + 'Cordapp-Workflow-Name' + 'Cordapp-Workflow-Version' + 'Cordapp-Workflow-Vendor' + 'Cordapp-Workflow-Licence' + +**Defaults** + +``Cordapp-Contract-Name`` (optional) if specified, the following Contract related attributes are also used: + + - ``Cordapp-Contract-Version`` (mandatory), must be a whole number starting from 1. + - ``Cordapp-Contract-Vendor`` (optional), defaults to UNKNOWN if not specified. + - ``Cordapp-Contract-Licence`` (optional), defaults to UNKNOWN if not specified. + +``Cordapp-Workflow-Name`` (optional) if specified, the following Workflow related attributes are also used: + + - ``Cordapp-Workflow-Version`` (mandatory), must be a whole number starting from 1. + - ``Cordapp-Workflow-Vendor`` (optional), defaults to UNKNOWN if not specified. + - ``Cordapp-Workflow-Licence`` (optional), defaults to UNKNOWN if not specified. + +As with the general CorDapp attributes (minimum and target platform version), these can be specified using the Gradle `cordapp` plugin as follows: + +For a contract only CorDapp we specify the `contract` tag: .. container:: codeset .. sourcecode:: groovy - jar { - manifest { - attributes( - 'Min-Platform-Version': 4 - 'Target-Platform-Version': 4 - ) + cordapp { + targetPlatformVersion 4 + minimumPlatformVersion 3 + contract { + name "my contract name" + versionId 1 + vendor "my company" + licence "my licence" } } + +For a CorDapp that contains flows and/or services we specify the `workflow` tag: + +.. container:: codeset + + .. sourcecode:: groovy + + cordapp { + targetPlatformVersion 4 + minimumPlatformVersion 3 + workflow { + name "my workflow name" + versionId 1 + vendor "my company" + licence "my licence" + } + } + +.. note:: It is possible, but *not recommended*, to include everything in a single CorDapp jar and use both the ``contract`` and ``workflow`` Gradle plugin tags. \ No newline at end of file diff --git a/experimental/notary-bft-smart/build.gradle b/experimental/notary-bft-smart/build.gradle index d9c0976b79..c94d9b8ba6 100644 --- a/experimental/notary-bft-smart/build.gradle +++ b/experimental/notary-bft-smart/build.gradle @@ -35,12 +35,13 @@ publish { name 'corda-notary-bft-smart' } - cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/experimental/notary-bft-smart" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/experimental/notary-raft/build.gradle b/experimental/notary-raft/build.gradle index adf7118c1c..db5715bf7e 100644 --- a/experimental/notary-raft/build.gradle +++ b/experimental/notary-raft/build.gradle @@ -36,10 +36,12 @@ publish { } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/experimental/notary-raft" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/finance/build.gradle b/finance/build.gradle index 5100a26afe..78eb6568a0 100644 --- a/finance/build.gradle +++ b/finance/build.gradle @@ -62,30 +62,22 @@ artifacts { jar { baseName 'corda-finance' - exclude "META-INF/*.DSA" - exclude "META-INF/*.RSA" - exclude "META-INF/*.SF" - exclude "META-INF/*.MF" - exclude "META-INF/LICENSE" - exclude "META-INF/NOTICE" - - manifest { - attributes( - "Manifest-Version": "1.0", - "Specification-Title": description, - "Specification-Version": version, - "Specification-Vendor": "Corda Open Source", - "Implementation-Title": "$group.$baseName", - ) - } } cordapp { - info { - name "net/corda/finance" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + contract { + name "net/corda/finance/contracts" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } + workflow { + name "net/corda/finance/flows" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } // By default the Cordapp is signed by Corda development certificate, for production build pass the following system properties to Gradle to use specific keystore e.g: // ./gradlew -Dsigning.enabled="true" -Dsigning.keystore="/path/to/keystore.jks" -Dsigning.alias="alias" -Dsigning.storepass="password" -Dsigning.keypass="password" diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderStaticContractTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderStaticContractTests.kt index 3ed92a38ac..1feb04b3db 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderStaticContractTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderStaticContractTests.kt @@ -4,13 +4,13 @@ import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.contracts.* -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.SecureHash import net.corda.core.identity.AbstractParty import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER import net.corda.core.internal.RPC_UPLOADER +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.node.ServicesForResolution import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.NetworkParametersStorage diff --git a/node/src/integration-test/kotlin/net/corda/contracts/SignatureConstraintVersioningTests.kt b/node/src/integration-test/kotlin/net/corda/contracts/SignatureConstraintVersioningTests.kt index 0f32140794..6e2f4bae56 100644 --- a/node/src/integration-test/kotlin/net/corda/contracts/SignatureConstraintVersioningTests.kt +++ b/node/src/integration-test/kotlin/net/corda/contracts/SignatureConstraintVersioningTests.kt @@ -35,8 +35,8 @@ import kotlin.test.assertNotNull class SignatureConstraintVersioningTests { private val base = cordappForPackages(MessageState::class.packageName, DummyMessageContract::class.packageName) - private val oldCordapp = base.withCordappVersion("2") - private val newCordapp = base.withCordappVersion("3") + private val oldCordapp = base.withVersion("2") + private val newCordapp = base.withVersion("3") private val user = User("mark", "dadada", setOf(startFlow(), startFlow(), invokeRpc("vaultQuery"))) private val message = Message("Hello world!") private val transformetMessage = Message(message.value + "A") diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index b178c1ca68..20e80ee3f4 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -243,9 +243,7 @@ open class NodeStartup : NodeStartupLogging { } protected open fun logLoadedCorDapps(corDapps: List) { - fun CordappImpl.Info.description() = "$shortName version $version by $vendor" - - Node.printBasicNodeInfo("Loaded ${corDapps.size} CorDapp(s)", corDapps.map { it.info }.joinToString(", ", transform = CordappImpl.Info::description)) + Node.printBasicNodeInfo("Loaded ${corDapps.size} CorDapp(s)", corDapps.map { it.info }.joinToString(", ")) corDapps.map { it.info }.filter { it.hasUnknownFields() }.let { malformed -> if (malformed.isNotEmpty()) { logger.warn("Found ${malformed.size} CorDapp(s) with unknown information. They will be unable to run on Corda in the future.") diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt index 3f9e9bb8f5..3a9aa1ccb7 100644 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt +++ b/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt @@ -9,7 +9,9 @@ import net.corda.core.crypto.sha256 import net.corda.core.flows.* import net.corda.core.internal.* import net.corda.core.internal.cordapp.CordappImpl +import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN import net.corda.core.internal.cordapp.CordappInfoResolver +import net.corda.core.internal.cordapp.toCordappInfo import net.corda.core.internal.notary.NotaryService import net.corda.core.internal.notary.SinglePartyNotaryService import net.corda.core.node.services.CordaService @@ -129,7 +131,7 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths: return cordapps } private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl { - val info = url.url.openStream().let(::JarInputStream).use { it.manifest?.toCordappInfo(CordappImpl.jarName(url.url)) ?: CordappImpl.Info.UNKNOWN } + val info = url.url.openStream().let(::JarInputStream).use { it.manifest?.toCordappInfo(CordappImpl.jarName(url.url)) ?: UNKNOWN } return CordappImpl( findContractClassNames(this), findInitiatedFlows(this), diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/ManifestUtils.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/ManifestUtils.kt deleted file mode 100644 index 0fd5fe8e08..0000000000 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/ManifestUtils.kt +++ /dev/null @@ -1,53 +0,0 @@ -package net.corda.node.internal.cordapp - -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION -import net.corda.core.internal.cordapp.CordappImpl -import net.corda.core.internal.cordapp.CordappImpl.Info.Companion.UNKNOWN_VALUE -import java.util.jar.Attributes -import java.util.jar.Manifest - -//TODO implementationVersion parmemater and update `Implementation-Version` when we finally agree on a naming split for Contracts vs Flows jars. -fun createTestManifest(name: String, title: String, version: String, vendor: String, targetVersion: Int, implementationVersion: String): Manifest { - val manifest = Manifest() - - // Mandatory manifest attribute. If not present, all other entries are silently skipped. - manifest.mainAttributes[Attributes.Name.MANIFEST_VERSION] = "1.0" - - manifest["Name"] = name - - manifest["Specification-Title"] = title - manifest["Specification-Version"] = version - manifest["Specification-Vendor"] = vendor - - manifest["Implementation-Title"] = title - manifest[Attributes.Name.IMPLEMENTATION_VERSION] = implementationVersion - manifest["Implementation-Vendor"] = vendor - manifest["Target-Platform-Version"] = targetVersion.toString() - - return manifest -} - -operator fun Manifest.set(key: String, value: String): String? { - return mainAttributes.putValue(key, value) -} - -operator fun Manifest.set(key: Attributes.Name, value: String): Any? { - return mainAttributes.put(key, value) -} - -operator fun Manifest.get(key: String): String? = mainAttributes.getValue(key) - -fun Manifest.toCordappInfo(defaultShortName: String): CordappImpl.Info { - val shortName = this["Name"] ?: defaultShortName - val vendor = this["Implementation-Vendor"] ?: UNKNOWN_VALUE - val version = this["Implementation-Version"] ?: DEFAULT_CORDAPP_VERSION.toString() - val minPlatformVersion = this["Min-Platform-Version"]?.toIntOrNull() ?: 1 - val targetPlatformVersion = this["Target-Platform-Version"]?.toIntOrNull() ?: minPlatformVersion - return CordappImpl.Info( - shortName = shortName, - vendor = vendor, - version = version, - minimumPlatformVersion = minPlatformVersion, - targetPlatformVersion = targetPlatformVersion - ) -} diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/VirtualCordapps.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/VirtualCordapps.kt index 8fa3d24222..6d567830a9 100644 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/VirtualCordapps.kt +++ b/node/src/main/kotlin/net/corda/node/internal/cordapp/VirtualCordapps.kt @@ -1,5 +1,6 @@ package net.corda.node.internal.cordapp +import net.corda.core.cordapp.Cordapp import net.corda.core.crypto.SecureHash import net.corda.core.flows.ContractUpgradeFlow import net.corda.core.internal.cordapp.CordappImpl @@ -28,7 +29,7 @@ internal object VirtualCordapp { serializationWhitelists = listOf(), serializationCustomSerializers = listOf(), customSchemas = setOf(), - info = CordappImpl.Info("corda-core", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion), + info = Cordapp.Info.Default("corda-core", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion), allFlows = listOf(), jarPath = ContractUpgradeFlow.javaClass.location, // Core JAR location jarHash = SecureHash.allOnesHash, @@ -49,7 +50,7 @@ internal object VirtualCordapp { serializationWhitelists = listOf(), serializationCustomSerializers = listOf(), customSchemas = setOf(NodeNotarySchemaV1), - info = CordappImpl.Info("corda-notary", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion), + info = Cordapp.Info.Default("corda-notary", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion), allFlows = listOf(), jarPath = SimpleNotaryService::class.java.location, jarHash = SecureHash.allOnesHash, diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt b/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt index ce63bcf6b0..c55400cd1d 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt @@ -7,18 +7,20 @@ import com.google.common.hash.Hashing import com.google.common.hash.HashingInputStream import com.google.common.io.CountingInputStream import net.corda.core.CordaRuntimeException -import net.corda.core.contracts.* -import net.corda.core.cordapp.CORDAPP_CONTRACT_VERSION +import net.corda.core.contracts.Attachment +import net.corda.core.contracts.ContractAttachment +import net.corda.core.contracts.ContractClassName import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 import net.corda.core.internal.* +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VERSION import net.corda.core.node.ServicesForResolution import net.corda.core.node.services.AttachmentId import net.corda.core.node.services.vault.AttachmentQueryCriteria import net.corda.core.node.services.vault.AttachmentSort import net.corda.core.serialization.* import net.corda.core.utilities.contextLogger -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.node.services.vault.HibernateAttachmentQueryCriteriaParser import net.corda.node.utilities.NonInvalidatingCache import net.corda.node.utilities.NonInvalidatingWeightBasedCache diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/NodeAttachmentServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/persistence/NodeAttachmentServiceTest.kt index 757e71650d..5b61833824 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/NodeAttachmentServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/NodeAttachmentServiceTest.kt @@ -4,16 +4,12 @@ import co.paralleluniverse.fibers.Suspendable import com.codahale.metrics.MetricRegistry import com.google.common.jimfs.Configuration import com.google.common.jimfs.Jimfs -import net.corda.testing.core.internal.ContractJarTestUtils.makeTestContractJar -import net.corda.testing.core.internal.ContractJarTestUtils.makeTestJar -import net.corda.testing.core.internal.ContractJarTestUtils.makeTestSignedContractJar -import net.corda.testing.core.internal.SelfCleaningDir import net.corda.core.contracts.ContractAttachment -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 import net.corda.core.flows.FlowLogic import net.corda.core.internal.* +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.node.ServicesForResolution import net.corda.core.node.services.vault.AttachmentQueryCriteria.AttachmentsQueryCriteria import net.corda.core.node.services.vault.AttachmentSort @@ -23,6 +19,10 @@ import net.corda.core.utilities.getOrThrow import net.corda.node.services.transactions.PersistentUniquenessProvider import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.DatabaseConfig +import net.corda.testing.core.internal.ContractJarTestUtils.makeTestContractJar +import net.corda.testing.core.internal.ContractJarTestUtils.makeTestJar +import net.corda.testing.core.internal.ContractJarTestUtils.makeTestSignedContractJar +import net.corda.testing.core.internal.SelfCleaningDir import net.corda.testing.internal.LogHelper import net.corda.testing.internal.TestingNamedCacheFactory import net.corda.testing.internal.configureDatabase diff --git a/samples/attachment-demo/build.gradle b/samples/attachment-demo/build.gradle index 7629c833fa..956920019f 100644 --- a/samples/attachment-demo/build.gradle +++ b/samples/attachment-demo/build.gradle @@ -114,10 +114,12 @@ jar { } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/attachment-demo" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/bank-of-corda-demo/build.gradle b/samples/bank-of-corda-demo/build.gradle index 135a51c921..beddf34a65 100644 --- a/samples/bank-of-corda-demo/build.gradle +++ b/samples/bank-of-corda-demo/build.gradle @@ -115,10 +115,12 @@ jar { } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/bank-of-corda-demo" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/cordapp-configuration/build.gradle b/samples/cordapp-configuration/build.gradle index 2203482080..d7e34631da 100644 --- a/samples/cordapp-configuration/build.gradle +++ b/samples/cordapp-configuration/build.gradle @@ -59,10 +59,12 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask, } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/cordapp-configuration" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/irs-demo/cordapp/build.gradle b/samples/irs-demo/cordapp/build.gradle index 0359cc52d1..2653979ea3 100644 --- a/samples/irs-demo/cordapp/build.gradle +++ b/samples/irs-demo/cordapp/build.gradle @@ -172,10 +172,18 @@ artifacts { } cordapp { - info { - name "net/corda/irs-demo" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + contract { + name "net/corda/irs-demo/contract" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } + workflow { + name "net/corda/irs-demo/flows" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/network-verifier/build.gradle b/samples/network-verifier/build.gradle index eea17b8ae2..e96ba9490f 100644 --- a/samples/network-verifier/build.gradle +++ b/samples/network-verifier/build.gradle @@ -53,10 +53,12 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask]) } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/network-verifier" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/notary-demo/build.gradle b/samples/notary-demo/build.gradle index d5b6a07a89..5435d4fbd8 100644 --- a/samples/notary-demo/build.gradle +++ b/samples/notary-demo/build.gradle @@ -255,10 +255,12 @@ jar { } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/notary-demo" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/simm-valuation-demo/build.gradle b/samples/simm-valuation-demo/build.gradle index 1d1408d0e0..a7e1e75972 100644 --- a/samples/simm-valuation-demo/build.gradle +++ b/samples/simm-valuation-demo/build.gradle @@ -140,8 +140,17 @@ task integrationTest(type: Test, dependsOn: []) { } cordapp { - info { - vendor = 'R3' - targetPlatformVersion = corda_platform_version.toInteger() + targetPlatformVersion = corda_platform_version.toInteger() + contract { + name "net/corda/vega/contracts" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } + workflow { + name "net/corda/vega/flows" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/samples/simm-valuation-demo/contracts-states/build.gradle b/samples/simm-valuation-demo/contracts-states/build.gradle index 17c3879883..fcb1e63cae 100644 --- a/samples/simm-valuation-demo/contracts-states/build.gradle +++ b/samples/simm-valuation-demo/contracts-states/build.gradle @@ -4,10 +4,8 @@ def javaHome = System.getProperty('java.home') def shrinkJar = file("$buildDir/libs/${project.name}-${project.version}-tiny.jar") cordapp { - info { - vendor = 'R3' - targetPlatformVersion = corda_platform_version.toInteger() - } + targetPlatformVersion = corda_platform_version.toInteger() + minimumPlatformVersion 1 signing { // Cordapp is signed after the "shrink" task. enabled false @@ -16,6 +14,12 @@ cordapp { // Cannot seal JAR because other module also defines classes in the package net.corda.vega.analytics enabled false } + contract { + name "net/corda/vega/contracts" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } } configurations { diff --git a/samples/simm-valuation-demo/flows/build.gradle b/samples/simm-valuation-demo/flows/build.gradle index 0c4626ea8f..fbb3a4dd58 100644 --- a/samples/simm-valuation-demo/flows/build.gradle +++ b/samples/simm-valuation-demo/flows/build.gradle @@ -2,14 +2,18 @@ apply plugin: 'net.corda.plugins.quasar-utils' apply plugin: 'net.corda.plugins.cordapp' cordapp { - info { - vendor = 'R3' - targetPlatformVersion = corda_platform_version.toInteger() - } + targetPlatformVersion = corda_platform_version.toInteger() + minimumPlatformVersion 1 sealing { // Cannot seal JAR because other module also defines classes in the package net.corda.vega.analytics enabled false } + workflow { + name "net/corda/vega/flows" + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" + } } dependencies { diff --git a/samples/trader-demo/build.gradle b/samples/trader-demo/build.gradle index 291f15d988..f5af7a9fc6 100644 --- a/samples/trader-demo/build.gradle +++ b/samples/trader-demo/build.gradle @@ -140,10 +140,12 @@ jar { } cordapp { - info { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion 1 + workflow { name "net/corda/samples/trader-demo" - vendor "Corda Open Source" - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion 1 + versionId 1 + vendor "R3" + licence "Open Source (Apache 2)" } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt index 1ff5d3b5c0..f2372b06f4 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt @@ -1,7 +1,6 @@ package net.corda.testing.node import net.corda.core.DoNotImplement -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.PLATFORM_VERSION import net.corda.testing.node.internal.TestCordappImpl import net.corda.testing.node.internal.simplifyScanPackages @@ -27,9 +26,6 @@ interface TestCordapp { /** Returns the target platform version, defaults to the current platform version if not specified. */ val targetVersion: Int - /** Returns the cordapp version. */ - val cordappVersion: String - /** Returns the config for this CorDapp, defaults to empty if not specified. */ val config: Map @@ -61,8 +57,6 @@ interface TestCordapp { * Optionally can pass in the location of an existing java key store to use */ fun signJar(keyStorePath: Path? = null): TestCordappImpl - fun withCordappVersion(version: String): TestCordappImpl - class Factory { companion object { /** @@ -80,11 +74,10 @@ interface TestCordapp { fun fromPackages(packageNames: Collection): TestCordapp { return TestCordappImpl( name = "test-name", - version = "1.0", + version = "1", vendor = "test-vendor", title = "test-title", targetVersion = PLATFORM_VERSION, - cordappVersion = DEFAULT_CORDAPP_VERSION.toString(), config = emptyMap(), packages = simplifyScanPackages(packageNames), classes = emptySet() diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappImpl.kt index 2f07df6dcd..171ac108d1 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappImpl.kt @@ -8,7 +8,6 @@ data class TestCordappImpl(override val name: String, override val vendor: String, override val title: String, override val targetVersion: Int, - override val cordappVersion: String, override val config: Map, override val packages: Set, override val signJar: Boolean = false, @@ -26,8 +25,6 @@ data class TestCordappImpl(override val name: String, override fun withTargetVersion(targetVersion: Int): TestCordappImpl = copy(targetVersion = targetVersion) - override fun withCordappVersion(version: String): TestCordappImpl = copy(cordappVersion = version) - override fun withConfig(config: Map): TestCordappImpl = copy(config = config) override fun signJar(keyStorePath: Path?): TestCordappImpl = copy(signJar = true, keyStorePath = keyStorePath) diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappsUtils.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappsUtils.kt index 1a104a4de1..f5eb5ebbf0 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappsUtils.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/TestCordappsUtils.kt @@ -1,15 +1,22 @@ package net.corda.testing.node.internal import io.github.classgraph.ClassGraph +import net.corda.core.internal.cordapp.* +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_VERSION +import net.corda.core.internal.cordapp.CordappImpl.Companion.TARGET_PLATFORM_VERSION import net.corda.core.internal.outputStream -import net.corda.node.internal.cordapp.createTestManifest import net.corda.testing.node.TestCordapp import java.io.BufferedOutputStream import java.nio.file.Path import java.nio.file.attribute.FileTime import java.time.Instant +import java.util.jar.Attributes import java.util.jar.JarFile import java.util.jar.JarOutputStream +import java.util.jar.Manifest import java.util.zip.ZipEntry import kotlin.reflect.KClass @@ -66,7 +73,7 @@ fun TestCordappImpl.packageAsJar(file: Path) { .scan() scanResult.use { - val manifest = createTestManifest(name, title, version, vendor, targetVersion, cordappVersion) + val manifest = createTestManifest(name, title, version, vendor, targetVersion) JarOutputStream(file.outputStream()).use { jos -> val time = FileTime.from(Instant.EPOCH) val manifestEntry = ZipEntry(JarFile.MANIFEST_NAME).setCreationTime(time).setLastAccessTime(time).setLastModifiedTime(time) @@ -85,3 +92,22 @@ fun TestCordappImpl.packageAsJar(file: Path) { } } } + +fun createTestManifest(name: String, title: String, version: String, vendor: String, targetVersion: Int): Manifest { + val manifest = Manifest() + + // Mandatory manifest attribute. If not present, all other entries are silently skipped. + manifest[Attributes.Name.MANIFEST_VERSION.toString()] = "1.0" + + manifest["Name"] = name + manifest[Attributes.Name.IMPLEMENTATION_TITLE] = title + manifest[Attributes.Name.IMPLEMENTATION_VERSION] = version + manifest[Attributes.Name.IMPLEMENTATION_VENDOR] = vendor + manifest[CORDAPP_CONTRACT_NAME] = name + manifest[CORDAPP_CONTRACT_VERSION] = version + manifest[CORDAPP_WORKFLOW_NAME] = name + manifest[CORDAPP_WORKFLOW_VERSION] = version + manifest[TARGET_PLATFORM_VERSION] = targetVersion.toString() + + return manifest +} diff --git a/testing/node-driver/src/test/kotlin/net/corda/testing/node/internal/TestCordappsUtilsTest.kt b/testing/node-driver/src/test/kotlin/net/corda/testing/node/internal/TestCordappsUtilsTest.kt index 581195dfc8..efd0bfe981 100644 --- a/testing/node-driver/src/test/kotlin/net/corda/testing/node/internal/TestCordappsUtilsTest.kt +++ b/testing/node-driver/src/test/kotlin/net/corda/testing/node/internal/TestCordappsUtilsTest.kt @@ -1,7 +1,10 @@ package net.corda.testing.node.internal +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_WORKFLOW_NAME +import net.corda.core.internal.cordapp.CordappImpl.Companion.TARGET_PLATFORM_VERSION +import net.corda.core.internal.cordapp.get import net.corda.core.internal.inputStream -import net.corda.node.internal.cordapp.get import org.assertj.core.api.Assertions.assertThat import org.junit.Rule import org.junit.Test @@ -34,8 +37,9 @@ class TestCordappsUtilsTest { val jarFile = packageAsJar(cordapp) JarInputStream(jarFile.inputStream()).use { - assertThat(it.manifest["Target-Platform-Version"]).isEqualTo("123") - assertThat(it.manifest["Name"]).isEqualTo("TestCordappsUtilsTest") + assertThat(it.manifest[TARGET_PLATFORM_VERSION]).isEqualTo("123") + assertThat(it.manifest[CORDAPP_CONTRACT_NAME]).isEqualTo("TestCordappsUtilsTest") + assertThat(it.manifest[CORDAPP_WORKFLOW_NAME]).isEqualTo("TestCordappsUtilsTest") } } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/core/internal/ContractJarTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/core/internal/ContractJarTestUtils.kt index 3acc58d38b..573aa77bb3 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/core/internal/ContractJarTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/core/internal/ContractJarTestUtils.kt @@ -1,18 +1,21 @@ package net.corda.testing.core.internal +import net.corda.core.internal.cordapp.CordappImpl.Companion.CORDAPP_CONTRACT_VERSION +import net.corda.core.internal.delete +import net.corda.core.internal.div +import net.corda.core.internal.toPath +import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.internal.JarSignatureTestUtils.addManifest import net.corda.testing.core.internal.JarSignatureTestUtils.createJar import net.corda.testing.core.internal.JarSignatureTestUtils.generateKey import net.corda.testing.core.internal.JarSignatureTestUtils.signJar -import net.corda.core.internal.delete -import net.corda.core.internal.div -import net.corda.core.internal.toPath -import net.corda.core.cordapp.CORDAPP_CONTRACT_VERSION -import net.corda.testing.core.ALICE_NAME import java.io.OutputStream import java.net.URI import java.net.URL -import java.nio.file.* +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import java.nio.file.StandardCopyOption import java.security.PublicKey import java.util.jar.Attributes import java.util.jar.JarEntry diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt index d72cdaaff0..7564e67c5c 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt @@ -16,7 +16,7 @@ import net.corda.core.schemas.MappedSchema import net.corda.core.serialization.internal.effectiveSerializationEnv import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.loggerFor -import net.corda.node.internal.cordapp.set +import net.corda.core.internal.cordapp.set import net.corda.node.internal.createCordaPersistence import net.corda.node.internal.security.RPCSecurityManagerImpl import net.corda.node.internal.startHikariPool diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt index 5291c124a2..199082a29b 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt @@ -5,6 +5,7 @@ import net.corda.core.cordapp.Cordapp import net.corda.core.crypto.SecureHash import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER import net.corda.core.internal.cordapp.CordappImpl +import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN import net.corda.core.node.services.AttachmentId import net.corda.core.node.services.AttachmentStorage import net.corda.node.cordapp.CordappLoader @@ -40,7 +41,7 @@ class MockCordappProvider( serializationCustomSerializers = emptyList(), customSchemas = emptySet(), jarPath = Paths.get("").toUri().toURL(), - info = CordappImpl.Info.UNKNOWN, + info = UNKNOWN, allFlows = emptyList(), jarHash = SecureHash.allOnesHash, notaryService = null diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/services/MockAttachmentStorage.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/services/MockAttachmentStorage.kt index 1e00d56cd2..65b64ccfbc 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/services/MockAttachmentStorage.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/services/MockAttachmentStorage.kt @@ -3,11 +3,11 @@ package net.corda.testing.services import net.corda.core.contracts.Attachment import net.corda.core.contracts.ContractAttachment import net.corda.core.contracts.ContractClassName -import net.corda.core.cordapp.DEFAULT_CORDAPP_VERSION import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 import net.corda.core.internal.AbstractAttachment import net.corda.core.internal.UNKNOWN_UPLOADER +import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION import net.corda.core.internal.readFully import net.corda.core.node.services.AttachmentId import net.corda.core.node.services.AttachmentStorage