mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
CORDA-1942: Moved minimumPlatformVersion and targetPlatformVersion to Cordapp (#4416)
Otherwise ContractAndWorkflow ends up having these two duplicated three times.
This commit is contained in:
parent
f2b6f96486
commit
1a065ef13d
@ -2,12 +2,10 @@ package net.corda.core.cordapp
|
|||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
import net.corda.core.DeleteForDJVM
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
|
import net.corda.core.cordapp.Cordapp.Info.*
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowLogic
|
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.UNKNOWN_VALUE
|
||||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.parseVersion
|
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
import net.corda.core.serialization.SerializationCustomSerializer
|
||||||
import net.corda.core.serialization.SerializationWhitelist
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
@ -21,7 +19,8 @@ import java.net.URL
|
|||||||
*
|
*
|
||||||
* This will only need to be constructed manually for certain kinds of tests.
|
* This will only need to be constructed manually for certain kinds of tests.
|
||||||
*
|
*
|
||||||
* @property name Cordapp name - derived from the base name of the Cordapp JAR (therefore may not be unique)
|
* @property name Cordapp name - derived from the base name of the Cordapp JAR (therefore may not be unique). This is different to
|
||||||
|
* [Cordapp.Info.shortName] which should be used instead.
|
||||||
* @property contractClassNames List of contracts
|
* @property contractClassNames List of contracts
|
||||||
* @property initiatedFlows List of initiatable flow classes
|
* @property initiatedFlows List of initiatable flow classes
|
||||||
* @property rpcFlows List of RPC initiable flows classes
|
* @property rpcFlows List of RPC initiable flows classes
|
||||||
@ -33,7 +32,10 @@ import java.net.URL
|
|||||||
* @property customSchemas List of custom schemas
|
* @property customSchemas List of custom schemas
|
||||||
* @property allFlows List of all flow classes
|
* @property allFlows List of all flow classes
|
||||||
* @property jarPath The path to the JAR for this CorDapp
|
* @property jarPath The path to the JAR for this CorDapp
|
||||||
|
* @property cordappClasses An exhaustive list of all classes relevant to the node within this CorDapp
|
||||||
* @property jarHash Hash of the jar
|
* @property jarHash Hash of the jar
|
||||||
|
* @property minimumPlatformVersion The minimum platform version this CorDapp will run on.
|
||||||
|
* @property targetPlatformVersion The target platform version this CorDapp was designed and tested on.
|
||||||
*/
|
*/
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
@DeleteForDJVM
|
@DeleteForDJVM
|
||||||
@ -53,11 +55,14 @@ interface Cordapp {
|
|||||||
val cordappClasses: List<String>
|
val cordappClasses: List<String>
|
||||||
val info: Info
|
val info: Info
|
||||||
val jarHash: SecureHash.SHA256
|
val jarHash: SecureHash.SHA256
|
||||||
|
val minimumPlatformVersion: Int
|
||||||
|
val targetPlatformVersion: Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CorDapp's information, including vendor and version.
|
* Further information about the CorDapp extracted from its MANIFEST. The sub-types [Default], [Contract] and [Workflow] determine what
|
||||||
|
* type of CorDapp this is.
|
||||||
*
|
*
|
||||||
* @property shortName Cordapp's shortName
|
* @property shortName Cordapp's name
|
||||||
* @property vendor Cordapp's vendor
|
* @property vendor Cordapp's vendor
|
||||||
* @property version Cordapp's version
|
* @property version Cordapp's version
|
||||||
*/
|
*/
|
||||||
@ -67,40 +72,44 @@ interface Cordapp {
|
|||||||
val vendor: String
|
val vendor: String
|
||||||
val version: String
|
val version: String
|
||||||
val licence: String
|
val licence: String
|
||||||
val minimumPlatformVersion: Int
|
|
||||||
val targetPlatformVersion: Int
|
|
||||||
|
|
||||||
fun hasUnknownFields(): Boolean
|
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)
|
* CorDapps created on V3 which bundle contracts and flows into the same jar. This is effectively
|
||||||
: Info {
|
* [ContractAndWorkflow] but without the integer versioning.
|
||||||
|
*/
|
||||||
|
data class Default(override val shortName: String, override val vendor: String, override val version: String, override val licence: String) : Info {
|
||||||
override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, version).any { it == UNKNOWN_VALUE }
|
override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, version).any { it == UNKNOWN_VALUE }
|
||||||
override fun toString() = "CorDapp $shortName version $version by $vendor with licence $licence"
|
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)
|
* A contract CorDapp contains contract definitions (state, commands) and verification logic
|
||||||
: Info {
|
* @property versionId integer version of the CorDapp. [version] is the toString of this.
|
||||||
|
*/
|
||||||
|
data class Contract(override val shortName: String, override val vendor: String, val versionId: Int, override val licence: String) : Info {
|
||||||
override val version: String
|
override val version: String
|
||||||
get() = versionId.toString()
|
get() = versionId.toString()
|
||||||
override fun toString() = "Contract CorDapp: $shortName version $version by vendor $vendor with licence $licence"
|
override fun toString() = "Contract CorDapp: $shortName version $versionId by vendor $vendor with licence $licence"
|
||||||
override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, licence).any { it == UNKNOWN_VALUE }
|
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)
|
* A workflow CorDapp contains flows and services used to implement business transactions using contracts and states persisted to the
|
||||||
: Info {
|
* immutable ledger
|
||||||
|
* @property versionId integer version of the CorDapp. [version] is the toString of this.
|
||||||
|
*/
|
||||||
|
data class Workflow(override val shortName: String, override val vendor: String, val versionId: Int, override val licence: String) : Info {
|
||||||
override val version: String
|
override val version: String
|
||||||
get() = versionId.toString()
|
get() = versionId.toString()
|
||||||
override fun toString() = "Workflow CorDapp: $shortName version $version by vendor $vendor with licence $licence"
|
override fun toString() = "Workflow CorDapp: $shortName version $versionId by vendor $vendor with licence $licence"
|
||||||
override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, licence).any { it == UNKNOWN_VALUE }
|
override fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, licence).any { it == UNKNOWN_VALUE }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A CorDapp that includes both Contract and Workflow classes (not recommended) */
|
/** A CorDapp that includes both contract and workflow classes, and defined in terms of [Contract] and [Workflow]. */
|
||||||
// TODO: future work in Gradle cordapp plugins to enforce separation of Contract and Workflow classes into separate jars
|
// 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)
|
data class ContractAndWorkflow(val contract: Contract, val workflow: Workflow) : Info {
|
||||||
: Info {
|
|
||||||
override val shortName: String
|
override val shortName: String
|
||||||
get() = "Contract: ${contract.shortName}, Workflow: ${workflow.shortName}"
|
get() = "Contract: ${contract.shortName}, Workflow: ${workflow.shortName}"
|
||||||
override val vendor: String
|
override val vendor: String
|
||||||
@ -108,7 +117,7 @@ interface Cordapp {
|
|||||||
override val licence: String
|
override val licence: String
|
||||||
get() = "Contract: ${contract.licence}, Workflow: ${workflow.licence}"
|
get() = "Contract: ${contract.licence}, Workflow: ${workflow.licence}"
|
||||||
override val version: String
|
override val version: String
|
||||||
get() = "Contract: ${contract.versionId}, Workflow: ${workflow.versionId}"
|
get() = "Contract: ${contract.version}, Workflow: ${workflow.version}"
|
||||||
override fun toString() = "Combined CorDapp: $contract, $workflow"
|
override fun toString() = "Combined CorDapp: $contract, $workflow"
|
||||||
override fun hasUnknownFields(): Boolean = contract.hasUnknownFields() || workflow.hasUnknownFields()
|
override fun hasUnknownFields(): Boolean = contract.hasUnknownFields() || workflow.hasUnknownFields()
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ package net.corda.core.internal.cordapp
|
|||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
import net.corda.core.DeleteForDJVM
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.cordapp.CordappInvalidVersionException
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.internal.notary.NotaryService
|
import net.corda.core.internal.notary.NotaryService
|
||||||
import net.corda.core.internal.toPath
|
import net.corda.core.internal.toPath
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
@ -12,6 +13,7 @@ import net.corda.core.serialization.SerializationCustomSerializer
|
|||||||
import net.corda.core.serialization.SerializationWhitelist
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
@DeleteForDJVM
|
@DeleteForDJVM
|
||||||
data class CordappImpl(
|
data class CordappImpl(
|
||||||
@ -28,11 +30,20 @@ data class CordappImpl(
|
|||||||
override val jarPath: URL,
|
override val jarPath: URL,
|
||||||
override val info: Cordapp.Info,
|
override val info: Cordapp.Info,
|
||||||
override val jarHash: SecureHash.SHA256,
|
override val jarHash: SecureHash.SHA256,
|
||||||
|
override val minimumPlatformVersion: Int,
|
||||||
|
override val targetPlatformVersion: Int,
|
||||||
val notaryService: Class<out NotaryService>?,
|
val notaryService: Class<out NotaryService>?,
|
||||||
/** Indicates whether the CorDapp is loaded from external sources, or generated on node startup (virtual). */
|
/** Indicates whether the CorDapp is loaded from external sources, or generated on node startup (virtual). */
|
||||||
val isLoaded: Boolean = true) : Cordapp {
|
val isLoaded: Boolean = true
|
||||||
|
) : Cordapp {
|
||||||
override val name: String = jarName(jarPath)
|
override val name: String = jarName(jarPath)
|
||||||
|
|
||||||
|
// TODO: Also add [SchedulableFlow] as a Cordapp class
|
||||||
|
override val cordappClasses: List<String> = run {
|
||||||
|
val classList = rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass } + notaryService
|
||||||
|
classList.mapNotNull { it?.name } + contractClassNames
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun jarName(url: URL): String = url.toPath().fileName.toString().removeSuffix(".jar")
|
fun jarName(url: URL): String = url.toPath().fileName.toString().removeSuffix(".jar")
|
||||||
|
|
||||||
@ -54,30 +65,26 @@ data class CordappImpl(
|
|||||||
const val DEFAULT_CORDAPP_VERSION = 1
|
const val DEFAULT_CORDAPP_VERSION = 1
|
||||||
|
|
||||||
/** used for CorDapps that do not explicitly define attributes */
|
/** used for CorDapps that do not explicitly define attributes */
|
||||||
val UNKNOWN = Cordapp.Info.Default(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE,1, 1)
|
val UNKNOWN_INFO = Cordapp.Info.Default(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE)
|
||||||
|
|
||||||
/** Helper method for version identifier parsing */
|
@VisibleForTesting
|
||||||
fun parseVersion(versionStr: String?, attributeName: String): Int {
|
val TEST_INSTANCE = CordappImpl(
|
||||||
if (versionStr == null)
|
contractClassNames = emptyList(),
|
||||||
throw CordappInvalidVersionException("Target versionId attribute $attributeName not specified. Please specify a whole number starting from 1.")
|
initiatedFlows = emptyList(),
|
||||||
return try {
|
rpcFlows = emptyList(),
|
||||||
val version = versionStr.toInt()
|
serviceFlows = emptyList(),
|
||||||
if (version < 1) {
|
schedulableFlows = emptyList(),
|
||||||
throw CordappInvalidVersionException("Target versionId ($versionStr) for attribute $attributeName must not be smaller than 1.")
|
services = emptyList(),
|
||||||
}
|
serializationWhitelists = emptyList(),
|
||||||
return version
|
serializationCustomSerializers = emptyList(),
|
||||||
} catch (e: NumberFormatException) {
|
customSchemas = emptySet(),
|
||||||
throw CordappInvalidVersionException("Version identifier ($versionStr) for attribute $attributeName must be a whole number starting from 1.")
|
jarPath = Paths.get("").toUri().toURL(),
|
||||||
}
|
info = CordappImpl.UNKNOWN_INFO,
|
||||||
}
|
allFlows = emptyList(),
|
||||||
}
|
jarHash = SecureHash.allOnesHash,
|
||||||
/**
|
minimumPlatformVersion = 1,
|
||||||
* An exhaustive list of all classes relevant to the node within this CorDapp
|
targetPlatformVersion = PLATFORM_VERSION,
|
||||||
*
|
notaryService = null
|
||||||
* TODO: Also add [SchedulableFlow] as a Cordapp class
|
)
|
||||||
*/
|
|
||||||
override val cordappClasses: List<String> = run {
|
|
||||||
val classList = rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass } + notaryService
|
|
||||||
classList.mapNotNull { it?.name } + contractClassNames
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,10 +11,10 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
*/
|
*/
|
||||||
object CordappInfoResolver {
|
object CordappInfoResolver {
|
||||||
private val logger = loggerFor<CordappInfoResolver>()
|
private val logger = loggerFor<CordappInfoResolver>()
|
||||||
private val cordappClasses: ConcurrentHashMap<String, Set<Cordapp.Info>> = ConcurrentHashMap()
|
private val cordappClasses: ConcurrentHashMap<String, Set<Cordapp>> = ConcurrentHashMap()
|
||||||
|
|
||||||
// TODO Use the StackWalker API once we migrate to Java 9+
|
// TODO Use the StackWalker API once we migrate to Java 9+
|
||||||
private var cordappInfoResolver: () -> Cordapp.Info? = {
|
private var cordappResolver: () -> Cordapp? = {
|
||||||
Exception().stackTrace
|
Exception().stackTrace
|
||||||
.mapNotNull { cordappClasses[it.className] }
|
.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.
|
// If there is more than one cordapp registered for a class name we can't determine the "correct" one and return null.
|
||||||
@ -26,8 +26,8 @@ object CordappInfoResolver {
|
|||||||
* This could happen when trying to run different versions of the same CorDapp on the same node.
|
* This could happen when trying to run different versions of the same CorDapp on the same node.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun register(classes: List<String>, cordapp: Cordapp.Info) {
|
fun register(cordapp: Cordapp) {
|
||||||
classes.forEach {
|
cordapp.cordappClasses.forEach {
|
||||||
if (cordappClasses.containsKey(it)) {
|
if (cordappClasses.containsKey(it)) {
|
||||||
logger.warn("More than one CorDapp registered for $it.")
|
logger.warn("More than one CorDapp registered for $it.")
|
||||||
cordappClasses[it] = cordappClasses[it]!! + cordapp
|
cordappClasses[it] = cordappClasses[it]!! + cordapp
|
||||||
@ -46,32 +46,28 @@ object CordappInfoResolver {
|
|||||||
* @return Information about the CorDapp from which the invoker is called, null if called outside a CorDapp or the
|
* @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.
|
* calling CorDapp cannot be reliably determined.
|
||||||
*/
|
*/
|
||||||
val currentCordappInfo: Cordapp.Info? get() = cordappInfoResolver()
|
val currentCordapp: Cordapp? get() = cordappResolver()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the target version of the current calling CorDapp. Defaults to the current platform version if there isn't one.
|
* Returns the target version of the current calling CorDapp. Defaults to the current platform version if there isn't one.
|
||||||
*/
|
*/
|
||||||
// TODO It may be the default is wrong and this should be Int? instead
|
// TODO It may be the default is wrong and this should be Int? instead
|
||||||
val currentTargetVersion: Int get() = currentCordappInfo?.targetPlatformVersion ?: PLATFORM_VERSION
|
val currentTargetVersion: Int get() = currentCordapp?.targetPlatformVersion ?: PLATFORM_VERSION
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporarily apply a fake CorDapp.Info with the given parameters. For use in testing.
|
* Temporarily apply a fake CorDapp with the given parameters. For use in testing.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun <T> withCordappInfo(shortName: String = "CordappInfoResolver.withCordappInfo",
|
fun <T> withCordapp(minimumPlatformVersion: Int = 1, targetPlatformVersion: Int = PLATFORM_VERSION, block: () -> T): T {
|
||||||
vendor: String = "Corda",
|
val currentResolver = cordappResolver
|
||||||
version: String = "1",
|
cordappResolver = {
|
||||||
licence: String = "Apache",
|
CordappImpl.TEST_INSTANCE.copy(minimumPlatformVersion = minimumPlatformVersion, targetPlatformVersion = targetPlatformVersion)
|
||||||
minimumPlatformVersion: Int = 1,
|
}
|
||||||
targetPlatformVersion: Int = PLATFORM_VERSION,
|
|
||||||
block: () -> T): T {
|
|
||||||
val currentResolver = cordappInfoResolver
|
|
||||||
cordappInfoResolver = { Cordapp.Info.Default(shortName, vendor, version, minimumPlatformVersion, targetPlatformVersion, licence) }
|
|
||||||
try {
|
try {
|
||||||
return block()
|
return block()
|
||||||
} finally {
|
} finally {
|
||||||
cordappInfoResolver = currentResolver
|
cordappResolver = currentResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,13 @@
|
|||||||
package net.corda.core.internal.cordapp
|
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.MIN_PLATFORM_VERSION
|
||||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.TARGET_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.Attributes
|
||||||
import java.util.jar.Manifest
|
import java.util.jar.Manifest
|
||||||
|
|
||||||
operator fun Manifest.set(key: String, value: String): String? {
|
operator fun Manifest.set(key: String, value: String): String? = mainAttributes.putValue(key, value)
|
||||||
return mainAttributes.putValue(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun Manifest.set(key: Attributes.Name, value: String): Any? {
|
operator fun Manifest.set(key: Attributes.Name, value: String): Any? = mainAttributes.put(key, value)
|
||||||
return mainAttributes.put(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun Manifest.get(key: String): String? = mainAttributes.getValue(key)
|
operator fun Manifest.get(key: String): String? = mainAttributes.getValue(key)
|
||||||
|
|
||||||
@ -31,56 +16,3 @@ val Manifest.targetPlatformVersion: Int
|
|||||||
val minPlatformVersion = this[MIN_PLATFORM_VERSION]?.toIntOrNull() ?: 1
|
val minPlatformVersion = this[MIN_PLATFORM_VERSION]?.toIntOrNull() ?: 1
|
||||||
return this[TARGET_PLATFORM_VERSION]?.toIntOrNull() ?: minPlatformVersion
|
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class FinalityFlowTests : WithFinality {
|
|||||||
fun `prevent use of the old API if the CorDapp target version is 4`() {
|
fun `prevent use of the old API if the CorDapp target version is 4`() {
|
||||||
val bob = createBob()
|
val bob = createBob()
|
||||||
val stx = aliceNode.issuesCashTo(bob)
|
val stx = aliceNode.issuesCashTo(bob)
|
||||||
val resultFuture = CordappInfoResolver.withCordappInfo(targetPlatformVersion = 4) {
|
val resultFuture = CordappInfoResolver.withCordapp(targetPlatformVersion = 4) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture
|
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ class FinalityFlowTests : WithFinality {
|
|||||||
// We need Bob to load at least one old CorDapp so that its FinalityHandler is enabled
|
// We need Bob to load at least one old CorDapp so that its FinalityHandler is enabled
|
||||||
val bob = createBob(cordapps = listOf(cordappForPackages("com.template").withTargetVersion(3)))
|
val bob = createBob(cordapps = listOf(cordappForPackages("com.template").withTargetVersion(3)))
|
||||||
val stx = aliceNode.issuesCashTo(bob)
|
val stx = aliceNode.issuesCashTo(bob)
|
||||||
val resultFuture = CordappInfoResolver.withCordappInfo(targetPlatformVersion = 3) {
|
val resultFuture = CordappInfoResolver.withCordapp(targetPlatformVersion = 3) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture
|
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.internal.cordapp
|
package net.corda.core.internal.cordapp
|
||||||
|
|
||||||
import net.corda.core.cordapp.Cordapp
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -18,11 +17,15 @@ class CordappInfoResolverTest {
|
|||||||
fun `the correct cordapp resolver is used after calling withCordappInfo`() {
|
fun `the correct cordapp resolver is used after calling withCordappInfo`() {
|
||||||
val defaultTargetVersion = 222
|
val defaultTargetVersion = 222
|
||||||
|
|
||||||
CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test", "test", "2", 3, defaultTargetVersion))
|
CordappInfoResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||||
|
contractClassNames = listOf(javaClass.name),
|
||||||
|
minimumPlatformVersion = 3,
|
||||||
|
targetPlatformVersion = defaultTargetVersion
|
||||||
|
))
|
||||||
assertEquals(defaultTargetVersion, CordappInfoResolver.currentTargetVersion)
|
assertEquals(defaultTargetVersion, CordappInfoResolver.currentTargetVersion)
|
||||||
|
|
||||||
val expectedTargetVersion = 555
|
val expectedTargetVersion = 555
|
||||||
CordappInfoResolver.withCordappInfo(targetPlatformVersion = expectedTargetVersion) {
|
CordappInfoResolver.withCordapp(targetPlatformVersion = expectedTargetVersion) {
|
||||||
val actualTargetVersion = CordappInfoResolver.currentTargetVersion
|
val actualTargetVersion = CordappInfoResolver.currentTargetVersion
|
||||||
assertEquals(expectedTargetVersion, actualTargetVersion)
|
assertEquals(expectedTargetVersion, actualTargetVersion)
|
||||||
}
|
}
|
||||||
@ -31,8 +34,16 @@ class CordappInfoResolverTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when more than one cordapp is registered for the same class, the resolver returns null`() {
|
fun `when more than one cordapp is registered for the same class, the resolver returns null`() {
|
||||||
CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test", "test", "2", 3, 222))
|
CordappInfoResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||||
CordappInfoResolver.register(listOf(javaClass.name), Cordapp.Info.Default("test1", "test1", "1", 2, 456))
|
contractClassNames = listOf(javaClass.name),
|
||||||
assertThat(CordappInfoResolver.currentCordappInfo).isNull()
|
minimumPlatformVersion = 3,
|
||||||
|
targetPlatformVersion = 222
|
||||||
|
))
|
||||||
|
CordappInfoResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||||
|
contractClassNames = listOf(javaClass.name),
|
||||||
|
minimumPlatformVersion = 2,
|
||||||
|
targetPlatformVersion = 456
|
||||||
|
))
|
||||||
|
assertThat(CordappInfoResolver.currentCordapp).isNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -693,7 +693,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
// TODO Add public API to allow the node operator to accept or reject
|
// TODO Add public API to allow the node operator to accept or reject
|
||||||
private fun installFinalityHandler() {
|
private fun installFinalityHandler() {
|
||||||
// Disable the insecure FinalityHandler if none of the loaded CorDapps are old enough to require it.
|
// Disable the insecure FinalityHandler if none of the loaded CorDapps are old enough to require it.
|
||||||
val cordappsNeedingFinalityHandler = cordappLoader.cordapps.filter { it.info.targetPlatformVersion < 4 }
|
val cordappsNeedingFinalityHandler = cordappLoader.cordapps.filter { it.targetPlatformVersion < 4 }
|
||||||
if (cordappsNeedingFinalityHandler.isEmpty()) {
|
if (cordappsNeedingFinalityHandler.isEmpty()) {
|
||||||
log.info("FinalityHandler is disabled as there are no CorDapps loaded which require it")
|
log.info("FinalityHandler is disabled as there are no CorDapps loaded which require it")
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,14 +4,15 @@ import io.github.classgraph.ClassGraph
|
|||||||
import io.github.classgraph.ScanResult
|
import io.github.classgraph.ScanResult
|
||||||
import net.corda.core.contracts.warnContractWithoutConstraintPropagation
|
import net.corda.core.contracts.warnContractWithoutConstraintPropagation
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.cordapp.CordappInvalidVersionException
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.sha256
|
import net.corda.core.crypto.sha256
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
import net.corda.core.internal.cordapp.CordappImpl
|
||||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN
|
import net.corda.core.internal.cordapp.CordappImpl.Companion.UNKNOWN_INFO
|
||||||
import net.corda.core.internal.cordapp.CordappInfoResolver
|
import net.corda.core.internal.cordapp.CordappInfoResolver
|
||||||
import net.corda.core.internal.cordapp.toCordappInfo
|
import net.corda.core.internal.cordapp.get
|
||||||
import net.corda.core.internal.notary.NotaryService
|
import net.corda.core.internal.notary.NotaryService
|
||||||
import net.corda.core.internal.notary.SinglePartyNotaryService
|
import net.corda.core.internal.notary.SinglePartyNotaryService
|
||||||
import net.corda.core.node.services.CordaService
|
import net.corda.core.node.services.CordaService
|
||||||
@ -31,6 +32,7 @@ import java.net.URLClassLoader
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.jar.JarInputStream
|
import java.util.jar.JarInputStream
|
||||||
|
import java.util.jar.Manifest
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.streams.toList
|
import kotlin.streams.toList
|
||||||
|
|
||||||
@ -89,7 +91,6 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
private fun URL.restricted(rootPackageName: String? = null) = RestrictedURL(this, rootPackageName)
|
private fun URL.restricted(rootPackageName: String? = null) = RestrictedURL(this, rootPackageName)
|
||||||
|
|
||||||
private fun jarUrlsInDirectory(directory: Path): List<URL> {
|
private fun jarUrlsInDirectory(directory: Path): List<URL> {
|
||||||
|
|
||||||
return if (!directory.exists()) {
|
return if (!directory.exists()) {
|
||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
@ -100,13 +101,14 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadCordapps(): List<CordappImpl> {
|
private fun loadCordapps(): List<CordappImpl> {
|
||||||
val cordapps = cordappJarPaths
|
val cordapps = cordappJarPaths
|
||||||
.map { url -> scanCordapp(url).use { it.toCordapp(url) } }
|
.map { url -> scanCordapp(url).use { it.toCordapp(url) } }
|
||||||
.filter {
|
.filter {
|
||||||
if (it.info.minimumPlatformVersion > versionInfo.platformVersion) {
|
if (it.minimumPlatformVersion > versionInfo.platformVersion) {
|
||||||
logger.warn("Not loading CorDapp ${it.info.shortName} (${it.info.vendor}) as it requires minimum " +
|
logger.warn("Not loading CorDapp ${it.info.shortName} (${it.info.vendor}) as it requires minimum " +
|
||||||
"platform version ${it.info.minimumPlatformVersion} (This node is running version ${versionInfo.platformVersion}).")
|
"platform version ${it.minimumPlatformVersion} (This node is running version ${versionInfo.platformVersion}).")
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
@ -127,11 +129,15 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cordapps.forEach { CordappInfoResolver.register(it.cordappClasses, it.info) }
|
cordapps.forEach(CordappInfoResolver::register)
|
||||||
return cordapps
|
return cordapps
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl {
|
private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl {
|
||||||
val info = url.url.openStream().let(::JarInputStream).use { it.manifest?.toCordappInfo(CordappImpl.jarName(url.url)) ?: UNKNOWN }
|
val manifest: Manifest? = url.url.openStream().use { JarInputStream(it).manifest }
|
||||||
|
val info = parseCordappInfo(manifest, CordappImpl.jarName(url.url))
|
||||||
|
val minPlatformVersion = manifest?.get(CordappImpl.MIN_PLATFORM_VERSION)?.toIntOrNull() ?: 1
|
||||||
|
val targetPlatformVersion = manifest?.get(CordappImpl.TARGET_PLATFORM_VERSION)?.toIntOrNull() ?: minPlatformVersion
|
||||||
return CordappImpl(
|
return CordappImpl(
|
||||||
findContractClassNames(this),
|
findContractClassNames(this),
|
||||||
findInitiatedFlows(this),
|
findInitiatedFlows(this),
|
||||||
@ -146,10 +152,67 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
|||||||
url.url,
|
url.url,
|
||||||
info,
|
info,
|
||||||
getJarHash(url.url),
|
getJarHash(url.url),
|
||||||
|
minPlatformVersion,
|
||||||
|
targetPlatformVersion,
|
||||||
findNotaryService(this)
|
findNotaryService(this)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseCordappInfo(manifest: Manifest?, defaultName: String): Cordapp.Info {
|
||||||
|
if (manifest == null) return UNKNOWN_INFO
|
||||||
|
|
||||||
|
/** new identifiers (Corda 4) */
|
||||||
|
// is it a Contract Jar?
|
||||||
|
val contractInfo = if (manifest[CordappImpl.CORDAPP_CONTRACT_NAME] != null) {
|
||||||
|
Cordapp.Info.Contract(
|
||||||
|
shortName = manifest[CordappImpl.CORDAPP_CONTRACT_NAME] ?: defaultName,
|
||||||
|
vendor = manifest[CordappImpl.CORDAPP_CONTRACT_VENDOR] ?: CordappImpl.UNKNOWN_VALUE,
|
||||||
|
versionId = parseVersion(manifest[CordappImpl.CORDAPP_CONTRACT_VERSION], CordappImpl.CORDAPP_CONTRACT_VERSION),
|
||||||
|
licence = manifest[CordappImpl.CORDAPP_CONTRACT_LICENCE] ?: CordappImpl.UNKNOWN_VALUE
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
// is it a Workflow (flows and services) Jar?
|
||||||
|
val workflowInfo = if (manifest[CordappImpl.CORDAPP_WORKFLOW_NAME] != null) {
|
||||||
|
Cordapp.Info.Workflow(
|
||||||
|
shortName = manifest[CordappImpl.CORDAPP_WORKFLOW_NAME] ?: defaultName,
|
||||||
|
vendor = manifest[CordappImpl.CORDAPP_WORKFLOW_VENDOR] ?: CordappImpl.UNKNOWN_VALUE,
|
||||||
|
versionId = parseVersion(manifest[CordappImpl.CORDAPP_WORKFLOW_VERSION], CordappImpl.CORDAPP_WORKFLOW_VERSION),
|
||||||
|
licence = manifest[CordappImpl.CORDAPP_WORKFLOW_LICENCE] ?: CordappImpl.UNKNOWN_VALUE
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
// combined Contract and Workflow Jar?
|
||||||
|
contractInfo != null && workflowInfo != null -> return Cordapp.Info.ContractAndWorkflow(contractInfo, workflowInfo)
|
||||||
|
contractInfo != null -> return contractInfo
|
||||||
|
workflowInfo != null -> return workflowInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cordapp.Info.Default(
|
||||||
|
shortName = manifest["Name"] ?: defaultName,
|
||||||
|
vendor = manifest["Implementation-Vendor"] ?: CordappImpl.UNKNOWN_VALUE,
|
||||||
|
version = manifest["Implementation-Version"] ?: CordappImpl.UNKNOWN_VALUE,
|
||||||
|
licence = CordappImpl.UNKNOWN_VALUE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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.")
|
||||||
|
}
|
||||||
|
val version = versionStr.toIntOrNull()
|
||||||
|
?: throw CordappInvalidVersionException("Version identifier ($versionStr) for attribute $attributeName must be a whole number starting from 1.")
|
||||||
|
if (version < 1) {
|
||||||
|
throw CordappInvalidVersionException("Target versionId ($versionStr) for attribute $attributeName must not be smaller than 1.")
|
||||||
|
}
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
private fun findNotaryService(scanResult: RestrictedScanResult): Class<out NotaryService>? {
|
private fun findNotaryService(scanResult: RestrictedScanResult): Class<out NotaryService>? {
|
||||||
// Note: we search for implementations of both NotaryService and TrustedAuthorityNotaryService as
|
// Note: we search for implementations of both NotaryService and TrustedAuthorityNotaryService as
|
||||||
// the scanner won't find subclasses deeper down the hierarchy if any intermediate class is not
|
// the scanner won't find subclasses deeper down the hierarchy if any intermediate class is not
|
||||||
|
@ -29,10 +29,12 @@ internal object VirtualCordapp {
|
|||||||
serializationWhitelists = listOf(),
|
serializationWhitelists = listOf(),
|
||||||
serializationCustomSerializers = listOf(),
|
serializationCustomSerializers = listOf(),
|
||||||
customSchemas = setOf(),
|
customSchemas = setOf(),
|
||||||
info = Cordapp.Info.Default("corda-core", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion),
|
info = Cordapp.Info.Default("corda-core", versionInfo.vendor, versionInfo.releaseVersion, "Open Source (Apache 2)"),
|
||||||
allFlows = listOf(),
|
allFlows = listOf(),
|
||||||
jarPath = ContractUpgradeFlow.javaClass.location, // Core JAR location
|
jarPath = ContractUpgradeFlow.javaClass.location, // Core JAR location
|
||||||
jarHash = SecureHash.allOnesHash,
|
jarHash = SecureHash.allOnesHash,
|
||||||
|
minimumPlatformVersion = 1,
|
||||||
|
targetPlatformVersion = versionInfo.platformVersion,
|
||||||
notaryService = null,
|
notaryService = null,
|
||||||
isLoaded = false
|
isLoaded = false
|
||||||
)
|
)
|
||||||
@ -50,10 +52,12 @@ internal object VirtualCordapp {
|
|||||||
serializationWhitelists = listOf(),
|
serializationWhitelists = listOf(),
|
||||||
serializationCustomSerializers = listOf(),
|
serializationCustomSerializers = listOf(),
|
||||||
customSchemas = setOf(NodeNotarySchemaV1),
|
customSchemas = setOf(NodeNotarySchemaV1),
|
||||||
info = Cordapp.Info.Default("corda-notary", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion),
|
info = Cordapp.Info.Default("corda-notary", versionInfo.vendor, versionInfo.releaseVersion, "Open Source (Apache 2)"),
|
||||||
allFlows = listOf(),
|
allFlows = listOf(),
|
||||||
jarPath = SimpleNotaryService::class.java.location,
|
jarPath = SimpleNotaryService::class.java.location,
|
||||||
jarHash = SecureHash.allOnesHash,
|
jarHash = SecureHash.allOnesHash,
|
||||||
|
minimumPlatformVersion = 1,
|
||||||
|
targetPlatformVersion = versionInfo.platformVersion,
|
||||||
notaryService = SimpleNotaryService::class.java,
|
notaryService = SimpleNotaryService::class.java,
|
||||||
isLoaded = false
|
isLoaded = false
|
||||||
)
|
)
|
||||||
|
@ -4,9 +4,9 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.internal.packageName
|
import net.corda.core.internal.packageName
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
|
import net.corda.nodeapi.internal.DEV_PUB_KEY_HASHES
|
||||||
import net.corda.testing.node.internal.TestCordappDirectories
|
import net.corda.testing.node.internal.TestCordappDirectories
|
||||||
import net.corda.testing.node.internal.cordappForPackages
|
import net.corda.testing.node.internal.cordappForPackages
|
||||||
import net.corda.nodeapi.internal.DEV_PUB_KEY_HASHES
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@ -96,8 +96,8 @@ class JarScanningCordappLoaderTest {
|
|||||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/no-min-or-target-version.jar")!!
|
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/no-min-or-target-version.jar")!!
|
||||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||||
loader.cordapps.forEach {
|
loader.cordapps.forEach {
|
||||||
assertThat(it.info.targetPlatformVersion).isEqualTo(1)
|
assertThat(it.targetPlatformVersion).isEqualTo(1)
|
||||||
assertThat(it.info.minimumPlatformVersion).isEqualTo(1)
|
assertThat(it.minimumPlatformVersion).isEqualTo(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ class JarScanningCordappLoaderTest {
|
|||||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
||||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||||
val cordapp = loader.cordapps.first()
|
val cordapp = loader.cordapps.first()
|
||||||
assertThat(cordapp.info.targetPlatformVersion).isEqualTo(3)
|
assertThat(cordapp.targetPlatformVersion).isEqualTo(3)
|
||||||
assertThat(cordapp.info.minimumPlatformVersion).isEqualTo(2)
|
assertThat(cordapp.minimumPlatformVersion).isEqualTo(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -119,8 +119,8 @@ class JarScanningCordappLoaderTest {
|
|||||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||||
// exclude the core cordapp
|
// exclude the core cordapp
|
||||||
val cordapp = loader.cordapps.single { it.cordappClasses.contains("net.corda.core.internal.cordapp.CordappImpl") }
|
val cordapp = loader.cordapps.single { it.cordappClasses.contains("net.corda.core.internal.cordapp.CordappImpl") }
|
||||||
assertThat(cordapp.info.targetPlatformVersion).isEqualTo(2)
|
assertThat(cordapp.targetPlatformVersion).isEqualTo(2)
|
||||||
assertThat(cordapp.info.minimumPlatformVersion).isEqualTo(2)
|
assertThat(cordapp.minimumPlatformVersion).isEqualTo(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -121,7 +121,7 @@ class FinalityHandlerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun TestStartedNode.finaliseWithOldApi(stx: SignedTransaction): CordaFuture<SignedTransaction> {
|
private fun TestStartedNode.finaliseWithOldApi(stx: SignedTransaction): CordaFuture<SignedTransaction> {
|
||||||
return CordappInfoResolver.withCordappInfo(targetPlatformVersion = 3) {
|
return CordappInfoResolver.withCordapp(targetPlatformVersion = 3) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
services.startFlow(FinalityFlow(stx)).resultFuture.apply {
|
services.startFlow(FinalityFlow(stx)).resultFuture.apply {
|
||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
|
@ -10,13 +10,13 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.NamedCacheFactory
|
import net.corda.core.internal.NamedCacheFactory
|
||||||
|
import net.corda.core.internal.cordapp.set
|
||||||
import net.corda.core.internal.createComponentGroups
|
import net.corda.core.internal.createComponentGroups
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
import net.corda.core.serialization.internal.effectiveSerializationEnv
|
import net.corda.core.serialization.internal.effectiveSerializationEnv
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.internal.cordapp.set
|
|
||||||
import net.corda.node.internal.createCordaPersistence
|
import net.corda.node.internal.createCordaPersistence
|
||||||
import net.corda.node.internal.security.RPCSecurityManagerImpl
|
import net.corda.node.internal.security.RPCSecurityManagerImpl
|
||||||
import net.corda.node.internal.startHikariPool
|
import net.corda.node.internal.startHikariPool
|
||||||
|
@ -2,16 +2,13 @@ package net.corda.testing.internal
|
|||||||
|
|
||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.cordapp.Cordapp
|
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.DEPLOYED_CORDAPP_UPLOADER
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
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.AttachmentId
|
||||||
import net.corda.core.node.services.AttachmentStorage
|
import net.corda.core.node.services.AttachmentStorage
|
||||||
import net.corda.node.cordapp.CordappLoader
|
import net.corda.node.cordapp.CordappLoader
|
||||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||||
import net.corda.testing.services.MockAttachmentStorage
|
import net.corda.testing.services.MockAttachmentStorage
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.jar.Attributes
|
import java.util.jar.Attributes
|
||||||
|
|
||||||
@ -30,22 +27,7 @@ class MockCordappProvider(
|
|||||||
signers: List<PublicKey> = emptyList(),
|
signers: List<PublicKey> = emptyList(),
|
||||||
jarManifestAttributes: Map<String,String> = emptyMap()
|
jarManifestAttributes: Map<String,String> = emptyMap()
|
||||||
): AttachmentId {
|
): AttachmentId {
|
||||||
val cordapp = CordappImpl(
|
val cordapp = CordappImpl.TEST_INSTANCE.copy(contractClassNames = listOf(contractClassName))
|
||||||
contractClassNames = listOf(contractClassName),
|
|
||||||
initiatedFlows = emptyList(),
|
|
||||||
rpcFlows = emptyList(),
|
|
||||||
serviceFlows = emptyList(),
|
|
||||||
schedulableFlows = emptyList(),
|
|
||||||
services = emptyList(),
|
|
||||||
serializationWhitelists = emptyList(),
|
|
||||||
serializationCustomSerializers = emptyList(),
|
|
||||||
customSchemas = emptySet(),
|
|
||||||
jarPath = Paths.get("").toUri().toURL(),
|
|
||||||
info = UNKNOWN,
|
|
||||||
allFlows = emptyList(),
|
|
||||||
jarHash = SecureHash.allOnesHash,
|
|
||||||
notaryService = null
|
|
||||||
)
|
|
||||||
val jarManifestAttributesWithObligatoryElement = jarManifestAttributes.toMutableMap()
|
val jarManifestAttributesWithObligatoryElement = jarManifestAttributes.toMutableMap()
|
||||||
jarManifestAttributesWithObligatoryElement.putIfAbsent(Attributes.Name.MANIFEST_VERSION.toString(), "1.0")
|
jarManifestAttributesWithObligatoryElement.putIfAbsent(Attributes.Name.MANIFEST_VERSION.toString(), "1.0")
|
||||||
if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) && it.second == contractHash }) {
|
if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) && it.second == contractHash }) {
|
||||||
|
Loading…
Reference in New Issue
Block a user