mirror of
https://github.com/corda/corda.git
synced 2025-04-07 19:34:41 +00:00
[CORDA-1926] Implement target version and min platform version (#3899)
https://r3-cev.atlassian.net/browse/CORDA-1926
This commit is contained in:
parent
06150371ad
commit
842eac5c43
@ -40,10 +40,11 @@ data class CordappImpl(
|
||||
override val cordappClasses: List<String> = (rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass }).map { 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) {
|
||||
data class Info(val shortName: String, val vendor: String, val version: String, val minimumPlatformVersion: Int, val targetPlatformVersion: Int) {
|
||||
companion object {
|
||||
private const val UNKNOWN_VALUE = "Unknown"
|
||||
val UNKNOWN = Info(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE)
|
||||
|
||||
val UNKNOWN = Info(UNKNOWN_VALUE, UNKNOWN_VALUE, UNKNOWN_VALUE, 1, 1)
|
||||
}
|
||||
|
||||
fun hasUnknownFields(): Boolean = arrayOf(shortName, vendor, version).any { it == UNKNOWN_VALUE }
|
||||
|
@ -0,0 +1,65 @@
|
||||
package net.corda.core.internal.cordapp
|
||||
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Provides a way to acquire information about the calling CorDapp.
|
||||
*/
|
||||
object CordappInfoResolver {
|
||||
private val logger = loggerFor<CordappInfoResolver>()
|
||||
private val cordappClasses: ConcurrentHashMap<String, Set<CordappImpl.Info>> = ConcurrentHashMap()
|
||||
|
||||
// TODO use the StackWalker API once we migrate to Java 9+
|
||||
private var cordappInfoResolver: () -> CordappImpl.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.
|
||||
.firstOrNull { it.size < 2 }?.single()
|
||||
}
|
||||
|
||||
/*
|
||||
* Associates class names with CorDapps or logs a warning when a CorDapp is already registered for a given class.
|
||||
* This could happen when trying to run different versions of the same CorDapp on the same node.
|
||||
*/
|
||||
@Synchronized
|
||||
fun register(classes: List<String>, cordapp: CordappImpl.Info) {
|
||||
classes.forEach {
|
||||
if (cordappClasses.containsKey(it)) {
|
||||
logger.warn("More than one CorDapp registered for $it.")
|
||||
cordappClasses[it] = cordappClasses[it]!! + cordapp
|
||||
} else {
|
||||
cordappClasses[it] = setOf(cordapp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This should only be used when making a change that would break compatibility with existing CorDapps. The change
|
||||
* can then be version-gated, meaning the old behaviour is used if the calling CorDapp's target version is lower
|
||||
* than the platform version that introduces the new behaviour.
|
||||
* In situations where a `[CordappProvider]` is available the CorDapp context should be obtained from there.
|
||||
*
|
||||
* @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..
|
||||
*/
|
||||
fun getCorDappInfo(): CordappImpl.Info? = cordappInfoResolver()
|
||||
|
||||
/**
|
||||
* Temporarily switch out the internal resolver for another one. For use in testing.
|
||||
*/
|
||||
@Synchronized
|
||||
fun withCordappInfoResolution(tempResolver: () -> CordappImpl.Info?, block: () -> Unit) {
|
||||
val resolver = cordappInfoResolver
|
||||
cordappInfoResolver = tempResolver
|
||||
try {
|
||||
block()
|
||||
} finally {
|
||||
cordappInfoResolver = resolver
|
||||
}
|
||||
}
|
||||
|
||||
internal fun clear() {
|
||||
cordappClasses.clear()
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package net.corda.core.internal.cordapp
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class CordappInfoResolverTest {
|
||||
|
||||
@Before
|
||||
@After
|
||||
fun clearCordappInfoResolver() {
|
||||
CordappInfoResolver.clear()
|
||||
}
|
||||
|
||||
@Test()
|
||||
fun `The correct cordapp resolver is used after calling withCordappResolution`() {
|
||||
val defaultTargetVersion = 222
|
||||
|
||||
CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test", "test", "2", 3, defaultTargetVersion))
|
||||
assertEquals(defaultTargetVersion, returnCallingTargetVersion())
|
||||
|
||||
val expectedTargetVersion = 555
|
||||
CordappInfoResolver.withCordappInfoResolution( { CordappImpl.Info("foo", "bar", "1", 2, expectedTargetVersion) })
|
||||
{
|
||||
val actualTargetVersion = returnCallingTargetVersion()
|
||||
assertEquals(expectedTargetVersion, actualTargetVersion)
|
||||
}
|
||||
assertEquals(defaultTargetVersion, returnCallingTargetVersion())
|
||||
}
|
||||
|
||||
@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))
|
||||
assertEquals(0, returnCallingTargetVersion())
|
||||
}
|
||||
|
||||
private fun returnCallingTargetVersion(): Int {
|
||||
return CordappInfoResolver.getCorDappInfo()?.targetPlatformVersion ?: 0
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ release, see :doc:`upgrade-notes`.
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
* Introduce minimum and target platform version for CorDapps.
|
||||
|
||||
* New overload for ``CordaRPCClient.start()`` method allowing to specify target legal identity to use for RPC call.
|
||||
|
||||
* Case insensitive vault queries can be specified via a boolean on applicable SQL criteria builder operators. By default queries will be case sensitive.
|
||||
|
@ -189,3 +189,30 @@ CorDapp configuration can be accessed from ``CordappContext::config`` whenever a
|
||||
|
||||
There is an example project that demonstrates in ``samples`` called ``cordapp-configuration`` and API documentation in
|
||||
`<api/kotlin/corda/net.corda.core.cordapp/index.html>`_.
|
||||
|
||||
|
||||
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:
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
'Min-Platform-Version': 3
|
||||
'Target-Platform-Version': 4
|
||||
|
||||
|
||||
In gradle, this can be achieved by modifying the jar task as shown in this example:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Min-Platform-Version': 3
|
||||
'Target-Platform-Version': 4
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,4 @@ and the release version - a change in the major, minor or patch values may or ma
|
||||
The Platform Version is part of the node's ``NodeInfo`` object, which is available from the ``ServiceHub``. This enables
|
||||
a CorDapp to find out which version it's running on and determine whether a desired feature is available. When a node
|
||||
registers with the Network Map Service it will use the node's Platform Version to enforce a minimum version requirement
|
||||
for the network.
|
||||
|
||||
.. note:: A future release may introduce the concept of a target platform version, which would be similar to Android's
|
||||
``targetSdkVersion``, and would provide a means of maintaining behavioural compatibility for the cases where the
|
||||
platform's behaviour has changed.
|
||||
for the network.
|
@ -15,6 +15,7 @@ import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||
import net.corda.node.internal.cordapp.JarScanningCordappLoader
|
||||
@ -110,7 +111,7 @@ class AttachmentsClassLoaderStaticContractTests {
|
||||
val cordapps = cordappsForPackages(packages)
|
||||
return testDirectory().let { directory ->
|
||||
cordapps.packageInDirectory(directory)
|
||||
JarScanningCordappLoader.fromDirectories(listOf(directory))
|
||||
JarScanningCordappLoader.fromDirectories(listOf(directory), VersionInfo.UNKNOWN)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,10 @@ import net.corda.core.serialization.SerializationFactory
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.internal.cordapp.JarScanningCordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||
import net.corda.nodeapi.internal.PLATFORM_VERSION
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
@ -50,7 +52,7 @@ class AttachmentLoadingTests {
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
private val attachments = MockAttachmentStorage()
|
||||
private val provider = CordappProviderImpl(JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR)), MockCordappConfigProvider(), attachments).apply {
|
||||
private val provider = CordappProviderImpl(JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR), VersionInfo.UNKNOWN), MockCordappConfigProvider(), attachments).apply {
|
||||
start(testNetworkParameters().whitelistedContractImplementations)
|
||||
}
|
||||
private val cordapp get() = provider.cordapps.first()
|
||||
|
@ -1,5 +1,7 @@
|
||||
package net.corda.node
|
||||
|
||||
import net.corda.nodeapi.internal.PLATFORM_VERSION
|
||||
|
||||
/**
|
||||
* Encapsulates various pieces of version information of the node.
|
||||
*/
|
||||
@ -17,6 +19,6 @@ data class VersionInfo(
|
||||
val vendor: String) {
|
||||
|
||||
companion object {
|
||||
val UNKNOWN = VersionInfo(1, "Unknown", "Unknown", "Unknown")
|
||||
val UNKNOWN = VersionInfo(PLATFORM_VERSION, "Unknown", "Unknown", "Unknown")
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ 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.CordappInfoResolver
|
||||
import net.corda.core.node.services.CordaService
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.serialization.SerializationCustomSerializer
|
||||
@ -35,7 +36,7 @@ import kotlin.streams.toList
|
||||
* @property cordappJarPaths The classpath of cordapp JARs
|
||||
*/
|
||||
class JarScanningCordappLoader private constructor(private val cordappJarPaths: List<RestrictedURL>,
|
||||
versionInfo: VersionInfo = VersionInfo.UNKNOWN) : CordappLoaderTemplate() {
|
||||
private val versionInfo: VersionInfo = VersionInfo.UNKNOWN) : CordappLoaderTemplate() {
|
||||
|
||||
override val cordapps: List<CordappImpl> by lazy { loadCordapps() + coreCordapp }
|
||||
|
||||
@ -104,13 +105,25 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
||||
serializationWhitelists = listOf(),
|
||||
serializationCustomSerializers = listOf(),
|
||||
customSchemas = setOf(),
|
||||
info = CordappImpl.Info("corda-core", versionInfo.vendor, versionInfo.releaseVersion),
|
||||
info = CordappImpl.Info("corda-core", versionInfo.vendor, versionInfo.releaseVersion, 1, versionInfo.platformVersion),
|
||||
allFlows = listOf(),
|
||||
jarPath = ContractUpgradeFlow.javaClass.location, // Core JAR location
|
||||
jarHash = SecureHash.allOnesHash
|
||||
)
|
||||
|
||||
private fun loadCordapps(): List<CordappImpl> = cordappJarPaths.map { scanCordapp(it).toCordapp(it) }
|
||||
private fun loadCordapps(): List<CordappImpl> {
|
||||
val cordapps = cordappJarPaths.map { scanCordapp(it).toCordapp(it) }
|
||||
.filter {
|
||||
if (it.info.minimumPlatformVersion > versionInfo.platformVersion) {
|
||||
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}).")
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
cordapps.forEach { CordappInfoResolver.register(it.cordappClasses, it.info) }
|
||||
return cordapps
|
||||
}
|
||||
|
||||
private fun RestrictedScanResult.toCordapp(url: RestrictedURL): CordappImpl {
|
||||
val info = url.url.openStream().let(::JarInputStream).use { it.manifest }.toCordappInfo(CordappImpl.jarName(url.url))
|
||||
|
@ -38,5 +38,8 @@ fun Manifest?.toCordappInfo(defaultShortName: String): CordappImpl.Info {
|
||||
this?.mainAttributes?.getValue("Implementation-Version")?.let { version ->
|
||||
info = info.copy(version = version)
|
||||
}
|
||||
val minPlatformVersion = this?.mainAttributes?.getValue("Min-Platform-Version")?.toInt() ?: 1
|
||||
val targetPlatformVersion = this?.mainAttributes?.getValue("Target-Platform-Version")?.toInt() ?: minPlatformVersion
|
||||
info = info.copy(minimumPlatformVersion = minPlatformVersion, targetPlatformVersion = targetPlatformVersion)
|
||||
return info
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ package net.corda.node.internal.cordapp
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import net.corda.core.node.services.AttachmentStorage
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.nodeapi.internal.PLATFORM_VERSION
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.internal.MockCordappConfigProvider
|
||||
import net.corda.testing.services.MockAttachmentStorage
|
||||
@ -75,7 +77,7 @@ class CordappProviderImplTests {
|
||||
fun `test cordapp configuration`() {
|
||||
val configProvider = MockCordappConfigProvider()
|
||||
configProvider.cordappConfigs[isolatedCordappName] = validConfig
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR))
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR), VersionInfo.UNKNOWN)
|
||||
val provider = CordappProviderImpl(loader, configProvider, attachmentStore).apply { start(whitelistedContractImplementations) }
|
||||
|
||||
val expected = provider.getAppContext(provider.cordapps.first()).config
|
||||
@ -84,7 +86,7 @@ class CordappProviderImplTests {
|
||||
}
|
||||
|
||||
private fun newCordappProvider(vararg urls: URL): CordappProviderImpl {
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(urls.toList())
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(urls.toList(), VersionInfo.UNKNOWN)
|
||||
return CordappProviderImpl(loader, stubConfigProvider, attachmentStore).apply { start(whitelistedContractImplementations) }
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ package net.corda.node.internal.cordapp
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.cordapp.CordappLoader
|
||||
import net.corda.nodeapi.internal.PLATFORM_VERSION
|
||||
import net.corda.testing.node.internal.cordappsForPackages
|
||||
import net.corda.testing.node.internal.getTimestampAsDirectoryName
|
||||
import net.corda.testing.node.internal.packageInDirectory
|
||||
@ -101,13 +103,70 @@ class JarScanningCordappLoaderTest {
|
||||
@Test
|
||||
fun `cordapp classloader can load cordapp classes`() {
|
||||
val isolatedJAR = JarScanningCordappLoaderTest::class.java.getResource("isolated.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR))
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(isolatedJAR), VersionInfo.UNKNOWN)
|
||||
|
||||
loader.appClassLoader.loadClass(isolatedContractId)
|
||||
loader.appClassLoader.loadClass(isolatedFlowName)
|
||||
}
|
||||
|
||||
private fun cordappLoaderForPackages(packages: Iterable<String>): CordappLoader {
|
||||
@Test
|
||||
fun `cordapp classloader sets target and min version to 1 if not specified`() {
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/no-min-or-target-version.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||
loader.cordapps.filter { !it.info.shortName.equals("corda-core") }.forEach {
|
||||
assertThat(it.info.targetPlatformVersion).isEqualTo(1)
|
||||
assertThat(it.info.minimumPlatformVersion).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cordapp classloader returns correct values for minPlatformVersion and targetVersion`() {
|
||||
// load jar with min and target version in manifest
|
||||
// make sure classloader extracts correct values
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||
// exclude the core cordapp
|
||||
val cordapp = loader.cordapps.filter { it.cordappClasses.contains("net.corda.core.internal.cordapp.CordappImpl")}.single()
|
||||
assertThat(cordapp.info.targetPlatformVersion).isEqualTo(3)
|
||||
assertThat(cordapp.info.minimumPlatformVersion).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cordapp classloader sets target version to min version if target version is not specified`() {
|
||||
// load jar with minVersion but not targetVersion in manifest
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-no-target.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN)
|
||||
// exclude the core cordapp
|
||||
val cordapp = loader.cordapps.filter { it.cordappClasses.contains("net.corda.core.internal.cordapp.CordappImpl")}.single()
|
||||
assertThat(cordapp.info.targetPlatformVersion).isEqualTo(2)
|
||||
assertThat(cordapp.info.minimumPlatformVersion).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cordapp classloader does not load apps when their min platform version is greater than the platform version`() {
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN.copy(platformVersion = 1))
|
||||
// exclude the core cordapp
|
||||
assertThat(loader.cordapps.size).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cordapp classloader does load apps when their min platform version is less than the platform version`() {
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN.copy(platformVersion = 1000))
|
||||
// exclude the core cordapp
|
||||
assertThat(loader.cordapps.size).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cordapp classloader does load apps when their min platform version is equal to the platform version`() {
|
||||
val jar = JarScanningCordappLoaderTest::class.java.getResource("versions/min-2-target-3.jar")!!
|
||||
val loader = JarScanningCordappLoader.fromJarUrls(listOf(jar), VersionInfo.UNKNOWN.copy(platformVersion = 2))
|
||||
// exclude the core cordapp
|
||||
assertThat(loader.cordapps.size).isEqualTo(2)
|
||||
}
|
||||
|
||||
private fun cordappLoaderForPackages(packages: Iterable<String>, versionInfo: VersionInfo = VersionInfo.UNKNOWN): CordappLoader {
|
||||
|
||||
val cordapps = cordappsForPackages(packages)
|
||||
return testDirectory().let { directory ->
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -18,6 +18,7 @@ import net.corda.core.node.services.*
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.cordapp.CordappLoader
|
||||
import net.corda.node.internal.ServicesForResolutionImpl
|
||||
import net.corda.node.internal.configureDatabase
|
||||
@ -27,6 +28,7 @@ import net.corda.node.services.identity.InMemoryIdentityService
|
||||
import net.corda.node.services.schema.NodeSchemaService
|
||||
import net.corda.node.services.transactions.InMemoryTransactionVerifierService
|
||||
import net.corda.node.services.vault.NodeVaultService
|
||||
import net.corda.nodeapi.internal.PLATFORM_VERSION
|
||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
|
||||
@ -69,10 +71,10 @@ open class MockServices private constructor(
|
||||
|
||||
companion object {
|
||||
|
||||
private fun cordappLoaderForPackages(packages: Iterable<String>): CordappLoader {
|
||||
private fun cordappLoaderForPackages(packages: Iterable<String>, versionInfo: VersionInfo = VersionInfo.UNKNOWN): CordappLoader {
|
||||
|
||||
val cordappPaths = TestCordappDirectories.forPackages(packages)
|
||||
return JarScanningCordappLoader.fromDirectories(cordappPaths)
|
||||
return JarScanningCordappLoader.fromDirectories(cordappPaths, versionInfo)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,7 +276,7 @@ open class InternalMockNetwork(defaultParameters: MockNetworkParameters = MockNe
|
||||
}
|
||||
}
|
||||
|
||||
open class MockNode(args: MockNodeArgs, cordappLoader: CordappLoader = JarScanningCordappLoader.fromDirectories(args.config.cordappDirectories)) : AbstractNode<TestStartedNode>(
|
||||
open class MockNode(args: MockNodeArgs, cordappLoader: CordappLoader = JarScanningCordappLoader.fromDirectories(args.config.cordappDirectories, args.version)) : AbstractNode<TestStartedNode>(
|
||||
args.config,
|
||||
TestClock(Clock.systemUTC()),
|
||||
DefaultNamedCacheFactory(),
|
||||
@ -474,7 +474,7 @@ open class InternalMockNetwork(defaultParameters: MockNetworkParameters = MockNe
|
||||
val cordappDirectories = sharedCorDappsDirectories + TestCordappDirectories.cached(cordapps)
|
||||
doReturn(cordappDirectories).whenever(config).cordappDirectories
|
||||
|
||||
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot, parameters.version), JarScanningCordappLoader.fromDirectories(cordappDirectories))
|
||||
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot, parameters.version), JarScanningCordappLoader.fromDirectories(cordappDirectories, parameters.version))
|
||||
_nodes += node
|
||||
if (start) {
|
||||
node.start()
|
||||
|
Loading…
x
Reference in New Issue
Block a user