ENT-11479 TransactionBuilder will not add legacy attachments once minimum platform version reaches 140 (4.12)

This commit is contained in:
rick.parker 2024-10-30 18:05:13 +00:00
parent d27aa0e685
commit 33592910ee
5 changed files with 23 additions and 8 deletions

View File

@ -19,4 +19,6 @@ object PlatformVersionSwitches {
const val RESTRICTED_DATABASE_OPERATIONS = 7 const val RESTRICTED_DATABASE_OPERATIONS = 7
const val CERTIFICATE_ROTATION = 9 const val CERTIFICATE_ROTATION = 9
const val TWO_PHASE_FINALITY = 13 const val TWO_PHASE_FINALITY = 13
const val LEGACY_ATTACHMENTS = 140
} }

View File

@ -17,7 +17,7 @@ interface CordappProviderInternal : CordappProvider {
* Similar to [getContractAttachmentID] except it returns the [ContractAttachment] object and also returns an optional second attachment * 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. * 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) data class ContractAttachmentWithLegacy(val currentAttachment: ContractAttachment, val legacyAttachment: ContractAttachment? = null)

View File

@ -695,10 +695,10 @@ open class TransactionBuilder(
contractClassName: String, contractClassName: String,
statesForException: () -> List<TransactionState<*>> statesForException: () -> List<TransactionState<*>>
): ContractAttachmentWithLegacy { ): ContractAttachmentWithLegacy {
// TODO Stop using legacy attachments when the 4.12 min platform version is reached https://r3-cev.atlassian.net/browse/ENT-11479 // Stop using legacy attachments when the 4.12 min platform version is reached
val attachmentWithLegacy = cordappProvider.getContractAttachments(contractClassName) val attachmentWithLegacy = cordappProvider.getContractAttachments(contractClassName, networkParameters.minimumPlatformVersion)
?: throw MissingContractAttachments(statesForException(), contractClassName) ?: 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 " + 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.") "transaction will not be compatible with older nodes.")
} }

View File

@ -6,6 +6,7 @@ import net.corda.core.cordapp.Cordapp
import net.corda.core.cordapp.CordappContext import net.corda.core.cordapp.CordappContext
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER 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.ContractAttachmentWithLegacy
import net.corda.core.internal.cordapp.CordappImpl import net.corda.core.internal.cordapp.CordappImpl
import net.corda.core.internal.cordapp.CordappProviderInternal import net.corda.core.internal.cordapp.CordappProviderInternal
@ -61,9 +62,10 @@ open class CordappProviderImpl(private val cordappLoader: CordappLoader,
return cordappLoader.cordapps.findCordapp(contractClassName) 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 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)) return ContractAttachmentWithLegacy(getContractAttachment(currentAttachmentId), legacyAttachmentId?.let(::getContractAttachment))
} }

View File

@ -2,6 +2,7 @@ package net.corda.node.internal.cordapp
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import net.corda.core.internal.PlatformVersionSwitches
import net.corda.core.internal.hash import net.corda.core.internal.hash
import net.corda.core.internal.toPath import net.corda.core.internal.toPath
import net.corda.core.node.services.AttachmentId import net.corda.core.node.services.AttachmentId
@ -134,9 +135,19 @@ class CordappProviderImplTests {
} }
@Test(timeout=300_000) @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 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(current.id).isEqualTo(currentFinanceContractsJar.hash)
assertThat(legacy?.id).isEqualTo(legacyFinanceContractsJar.hash) assertThat(legacy?.id).isEqualTo(legacyFinanceContractsJar.hash)
// getContractAttachmentID should always return the non-legacy attachment ID // getContractAttachmentID should always return the non-legacy attachment ID