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 721d06bc15..366daabedc 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 @@ -34,14 +34,15 @@ data class CordappImpl( override val targetPlatformVersion: Int, val notaryService: Class? = null, /** Indicates whether the CorDapp is loaded from external sources, or generated on node startup (virtual). */ - val isLoaded: Boolean = true + val isLoaded: Boolean = true, + private val explicitCordappClasses: List = emptyList() ) : Cordapp { override val name: String = jarName(jarPath) // TODO: Also add [SchedulableFlow] as a Cordapp class override val cordappClasses: List = run { val classList = rpcFlows + initiatedFlows + services + serializationWhitelists.map { javaClass } + notaryService - classList.mapNotNull { it?.name } + contractClassNames + classList.mapNotNull { it?.name } + contractClassNames + explicitCordappClasses } companion object { diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappResolver.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappResolver.kt index 250ecb3e39..ff7fe11207 100644 --- a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappResolver.kt +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappResolver.kt @@ -55,10 +55,10 @@ object CordappResolver { 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 platform version 1 if there isn't one, + * assuming only basic platform capabilities. */ - // TODO It may be the default is wrong and this should be Int? instead - val currentTargetVersion: Int get() = currentCordapp?.targetPlatformVersion ?: PLATFORM_VERSION + val currentTargetVersion: Int get() = currentCordapp?.targetPlatformVersion ?: 1 /** * Temporarily apply a fake CorDapp with the given parameters. For use in testing. 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 d4d181a388..4881ebf5e7 100644 --- a/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt +++ b/core/src/test/kotlin/net/corda/core/transactions/TransactionBuilderTest.kt @@ -11,6 +11,7 @@ import net.corda.core.identity.Party import net.corda.core.internal.AbstractAttachment import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION +import net.corda.core.internal.cordapp.CordappResolver import net.corda.core.node.ServicesForResolution import net.corda.core.node.ZoneVersionTooLowException import net.corda.core.node.services.AttachmentStorage @@ -116,20 +117,22 @@ class TransactionBuilderTest { @Test fun `multiple commands with same data are joined without duplicates in terms of signers`() { - val aliceParty = TestIdentity(ALICE_NAME).party - val bobParty = TestIdentity(BOB_NAME).party - val tx = TransactionBuilder(notary) - tx.addCommand(DummyCommandData, notary.owningKey, aliceParty.owningKey) - tx.addCommand(DummyCommandData, aliceParty.owningKey, bobParty.owningKey) + // This behaviour is only activated for platform version 4 onwards. + CordappResolver.withCordapp(targetPlatformVersion = 4) { + val aliceParty = TestIdentity(ALICE_NAME).party + val bobParty = TestIdentity(BOB_NAME).party + val tx = TransactionBuilder(notary) + tx.addCommand(DummyCommandData, notary.owningKey, aliceParty.owningKey) + tx.addCommand(DummyCommandData, aliceParty.owningKey, bobParty.owningKey) - val commands = tx.commands() + val commands = tx.commands() - assertThat(commands).hasSize(1) - assertThat(commands.single()).satisfies { cmd -> - - assertThat(cmd.value).isEqualTo(DummyCommandData) - assertThat(cmd.signers).hasSize(3) - assertThat(cmd.signers).contains(notary.owningKey, bobParty.owningKey, aliceParty.owningKey) + assertThat(commands).hasSize(1) + assertThat(commands.single()).satisfies { cmd -> + assertThat(cmd.value).isEqualTo(DummyCommandData) + assertThat(cmd.signers).hasSize(3) + assertThat(cmd.signers).contains(notary.owningKey, bobParty.owningKey, aliceParty.owningKey) + } } } 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 5518e985f1..4ffc90959b 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 @@ -151,7 +151,8 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths: getJarHash(url.url), minPlatformVersion, targetPlatformVersion, - findNotaryService(this) + findNotaryService(this), + explicitCordappClasses = findAllCordappClasses(this) ) } @@ -250,6 +251,10 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths: return scanResult.getConcreteClassesOfType(FlowLogic::class) } + private fun findAllCordappClasses(scanResult: RestrictedScanResult): List { + return scanResult.getAllStandardClasses() + scanResult.getAllInterfaces() + } + private fun findContractClassNames(scanResult: RestrictedScanResult): List { val contractClasses = coreContractClasses.flatMap { scanResult.getNamesOfClassesImplementing(it) }.distinct() for (contractClass in contractClasses) { @@ -350,6 +355,20 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths: .filterNot { it.isAbstractClass } } + fun getAllStandardClasses(): List { + return scanResult + .getAllStandardClasses() + .names + .filter { it.startsWith(qualifiedNamePrefix) } + } + + fun getAllInterfaces(): List { + return scanResult + .getAllInterfaces() + .names + .filter { it.startsWith(qualifiedNamePrefix) } + } + override fun close() = scanResult.close() } }