diff --git a/core-tests/src/integration-test/kotlin/net/corda/coretests/transactions/TransactionBuilderDriverTest.kt b/core-tests/src/integration-test/kotlin/net/corda/coretests/transactions/TransactionBuilderDriverTest.kt index db8695c445..22af6864e2 100644 --- a/core-tests/src/integration-test/kotlin/net/corda/coretests/transactions/TransactionBuilderDriverTest.kt +++ b/core-tests/src/integration-test/kotlin/net/corda/coretests/transactions/TransactionBuilderDriverTest.kt @@ -37,6 +37,7 @@ import net.corda.testing.node.internal.TestCordappInternal import net.corda.testing.node.internal.UriTestCordapp import net.corda.testing.node.internal.enclosedCordapp import net.corda.testing.node.internal.internalDriver +import org.apache.commons.io.FileUtils import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy import org.junit.Test @@ -114,10 +115,20 @@ class TransactionBuilderDriverTest { createTransaction(node, bobParty) }.hasMessageContaining("Transaction being built has a missing legacy attachment for class net/corda/finance/contracts/asset/") - // Upload the missing dependency - legacyDependency.jarFile.inputStream().use(node.rpc::uploadAttachment) + node.stop() + FileUtils.deleteDirectory(node.baseDirectory.toFile()); - val stx = createTransaction(node, bobParty) + // Now restart the node with the missing dependency + val restartedNode = startNode(NodeParameters( + ALICE_NAME, + additionalCordapps = listOf(currentContracts), + legacyContracts = listOf(legacyContracts, legacyDependency) + )).getOrThrow() + + // Attachment does not have a contract in it so needs to be manually installed into attachment db storage + legacyDependency.jarFile.inputStream().use(restartedNode.rpc::uploadAttachment) + + val stx = createTransaction(restartedNode, bobParty) assertThat(stx.tx.legacyAttachments).contains(legacyContracts.jarFile.hash, legacyDependency.jarFile.hash) } } 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 a3e6036370..8dd9c16493 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 @@ -11,6 +11,7 @@ interface CordappProviderInternal : CordappProvider { val appClassLoader: ClassLoader val attachmentFixups: AttachmentFixups val cordapps: List + val legacyContractCordapps: List fun getCordappForFlow(flowLogic: FlowLogic<*>): Cordapp? /** 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 ca3d9784fa..46be9c90a8 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -349,9 +349,9 @@ open class TransactionBuilder( val attachments = serviceHub.getTrustedClassAttachments(missingClass) val attachment = if (isLegacy) { - // Any attachment which contains the class but isn't a non-legacy CorDapp is *probably* the legacy attachment we're looking for - val nonLegacyCordapps = serviceHub.cordappProvider.cordapps.mapToSet { it.jarHash } - attachments.firstOrNull { it.id !in nonLegacyCordapps } + // Any (legacy) missing attachments must also be present in the legacy-contracts folder to be attached to a transaction + val legacyContractCordapps = serviceHub.cordappProvider.legacyContractCordapps.mapToSet { it.jarHash } + attachments.firstOrNull { it.id in legacyContractCordapps } } else { attachments.firstOrNull() } 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 c11aa324c4..b80554f1da 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 @@ -38,6 +38,8 @@ open class CordappProviderImpl(private val cordappLoader: CordappLoader, */ override val cordapps: List get() = cordappLoader.cordapps + override val legacyContractCordapps: List get() = cordappLoader.legacyContractCordapps + fun start() { loadContractsIntoAttachmentStore(cordappLoader.cordapps) loadContractsIntoAttachmentStore(cordappLoader.legacyContractCordapps)