diff --git a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt index f40ea96c6c..e32044ac02 100644 --- a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt +++ b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt @@ -19,4 +19,6 @@ object PlatformVersionSwitches { const val RESTRICTED_DATABASE_OPERATIONS = 7 const val CERTIFICATE_ROTATION = 9 const val TWO_PHASE_FINALITY = 13 + const val LEGACY_ATTACHMENTS = 140 + } \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappProviderInternal.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappProviderInternal.kt index fd83ba26f1..a3e6036370 100644 --- a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappProviderInternal.kt +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappProviderInternal.kt @@ -17,7 +17,7 @@ interface CordappProviderInternal : CordappProvider { * Similar to [getContractAttachmentID] except it returns the [ContractAttachment] object and also returns an optional second attachment * representing the legacy version (4.11 or earlier) of the contract, if one exists. */ - fun getContractAttachments(contractClassName: ContractClassName): ContractAttachmentWithLegacy? + fun getContractAttachments(contractClassName: ContractClassName, minimumPlatformVersion: Int): ContractAttachmentWithLegacy? } data class ContractAttachmentWithLegacy(val currentAttachment: ContractAttachment, val legacyAttachment: ContractAttachment? = null) 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 d954abda92..221a31cc84 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -695,10 +695,10 @@ open class TransactionBuilder( contractClassName: String, statesForException: () -> List> ): ContractAttachmentWithLegacy { - // TODO Stop using legacy attachments when the 4.12 min platform version is reached https://r3-cev.atlassian.net/browse/ENT-11479 - val attachmentWithLegacy = cordappProvider.getContractAttachments(contractClassName) + // Stop using legacy attachments when the 4.12 min platform version is reached + val attachmentWithLegacy = cordappProvider.getContractAttachments(contractClassName, networkParameters.minimumPlatformVersion) ?: throw MissingContractAttachments(statesForException(), contractClassName) - if (attachmentWithLegacy.legacyAttachment == null) { + if (networkParameters.minimumPlatformVersion < PlatformVersionSwitches.LEGACY_ATTACHMENTS && attachmentWithLegacy.legacyAttachment == null) { log.warnOnce("Contract $contractClassName does not have a legacy (4.11 or earlier) version installed. This means the " + "transaction will not be compatible with older nodes.") } diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappProviderImpl.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappProviderImpl.kt index 60e6483074..c11aa324c4 100644 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappProviderImpl.kt +++ b/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappProviderImpl.kt @@ -6,6 +6,7 @@ import net.corda.core.cordapp.Cordapp import net.corda.core.cordapp.CordappContext import net.corda.core.flows.FlowLogic import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER +import net.corda.core.internal.PlatformVersionSwitches import net.corda.core.internal.cordapp.ContractAttachmentWithLegacy import net.corda.core.internal.cordapp.CordappImpl import net.corda.core.internal.cordapp.CordappProviderInternal @@ -61,9 +62,10 @@ open class CordappProviderImpl(private val cordappLoader: CordappLoader, return cordappLoader.cordapps.findCordapp(contractClassName) } - override fun getContractAttachments(contractClassName: ContractClassName): ContractAttachmentWithLegacy? { + override fun getContractAttachments(contractClassName: ContractClassName, minimumPlatformVersion: Int): ContractAttachmentWithLegacy? { val currentAttachmentId = getContractAttachmentID(contractClassName) ?: return null - val legacyAttachmentId = cordappLoader.legacyContractCordapps.findCordapp(contractClassName) + val legacyAttachmentId = if (minimumPlatformVersion < PlatformVersionSwitches.LEGACY_ATTACHMENTS) + cordappLoader.legacyContractCordapps.findCordapp(contractClassName) else null return ContractAttachmentWithLegacy(getContractAttachment(currentAttachmentId), legacyAttachmentId?.let(::getContractAttachment)) } diff --git a/node/src/test/kotlin/net/corda/node/internal/cordapp/CordappProviderImplTests.kt b/node/src/test/kotlin/net/corda/node/internal/cordapp/CordappProviderImplTests.kt index 88942ca7cc..395e10bcf5 100644 --- a/node/src/test/kotlin/net/corda/node/internal/cordapp/CordappProviderImplTests.kt +++ b/node/src/test/kotlin/net/corda/node/internal/cordapp/CordappProviderImplTests.kt @@ -2,6 +2,7 @@ package net.corda.node.internal.cordapp import com.typesafe.config.Config import com.typesafe.config.ConfigFactory +import net.corda.core.internal.PlatformVersionSwitches import net.corda.core.internal.hash import net.corda.core.internal.toPath import net.corda.core.node.services.AttachmentId @@ -134,9 +135,19 @@ class CordappProviderImplTests { } @Test(timeout=300_000) - fun `retrieving legacy attachment for contract`() { + fun `retrieving legacy attachment for contract on network that does not support pre-412 `() { val provider = newCordappProvider(setOf(currentFinanceContractsJar), setOf(legacyFinanceContractsJar)) - val (current, legacy) = provider.getContractAttachments(Cash::class.java.name)!! + val (current, legacy) = provider.getContractAttachments(Cash::class.java.name, PlatformVersionSwitches.LEGACY_ATTACHMENTS)!! + assertThat(current.id).isEqualTo(currentFinanceContractsJar.hash) + assertThat(legacy?.id).isNull() + // getContractAttachmentID should always return the non-legacy attachment ID + assertThat(provider.getContractAttachmentID(Cash::class.java.name)).isEqualTo(currentFinanceContractsJar.hash) + } + + @Test(timeout = 300_000) + fun `retrieving legacy attachment for contract on mixed network of versions`() { + val provider = newCordappProvider(setOf(currentFinanceContractsJar), setOf(legacyFinanceContractsJar)) + val (current, legacy) = provider.getContractAttachments(Cash::class.java.name, PlatformVersionSwitches.LEGACY_ATTACHMENTS - 1)!! assertThat(current.id).isEqualTo(currentFinanceContractsJar.hash) assertThat(legacy?.id).isEqualTo(legacyFinanceContractsJar.hash) // getContractAttachmentID should always return the non-legacy attachment ID