mirror of
https://github.com/corda/corda.git
synced 2025-06-24 02:04:12 +00:00
CORDA-2475 Adjust attachments query logic to return correct results (#4612)
* CORDA-2475 Adjust attachments query logic to return correct results sets for signed/unsigned jars. * Updates following PR review feedback by RP.
This commit is contained in:
@ -1,10 +1,9 @@
|
||||
package net.corda.core.node.services
|
||||
|
||||
import net.corda.core.CordaInternal
|
||||
import net.corda.core.DoNotImplement
|
||||
import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.contracts.ContractAttachment
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
|
||||
import net.corda.core.node.services.vault.AttachmentQueryCriteria
|
||||
import net.corda.core.node.services.vault.AttachmentSort
|
||||
import java.io.IOException
|
||||
@ -79,22 +78,15 @@ interface AttachmentStorage {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Attachment Id of the contract attachment with the highest version for a given contract class name
|
||||
* from trusted upload sources. If both a signed and unsigned attachment exist, prefer the signed one.
|
||||
* Find the Attachment Id(s) of the contract attachments with the highest version for a given contract class name
|
||||
* from trusted upload sources.
|
||||
* Return highest version of both signed and unsigned attachment ids (signed first, unsigned second), otherwise return a
|
||||
* single signed or unsigned version id, or an empty list if none meet the criteria.
|
||||
*
|
||||
* @param contractClassName The fully qualified name of the contract class.
|
||||
* @param minContractVersion The minimum contract version that should be returned.
|
||||
* @return the [AttachmentId] of the contract, or null if none meet the criteria.
|
||||
* @return the [AttachmentId]s of the contract attachments (signed always first in list), or an empty list if none meet the criteria.
|
||||
*/
|
||||
fun getContractAttachmentWithHighestContractVersion(contractClassName: String, minContractVersion: Int): AttachmentId?
|
||||
|
||||
/**
|
||||
* Find the Attachment Ids of the contract attachments for a given contract class name
|
||||
* from trusted upload sources.
|
||||
*
|
||||
* @param contractClassName The fully qualified name of the contract class.
|
||||
* @return the [AttachmentId]s of the contract attachments, or an empty set if none meet the criteria.
|
||||
*/
|
||||
fun getContractAttachments(contractClassName: String): Set<AttachmentId>
|
||||
fun getLatestContractAttachments(contractClassName: String, minContractVersion: Int = DEFAULT_CORDAPP_VERSION): List<AttachmentId>
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ open class TransactionBuilder(
|
||||
val outputHashConstraints = outputStates?.filter { it.constraint is HashAttachmentConstraint } ?: emptyList()
|
||||
val outputSignatureConstraints = outputStates?.filter { it.constraint is SignatureAttachmentConstraint } ?: emptyList()
|
||||
if (inputsHashConstraints.isNotEmpty() && (outputHashConstraints.isNotEmpty() || outputSignatureConstraints.isNotEmpty())) {
|
||||
val attachmentIds = services.attachments.getContractAttachments(contractClassName)
|
||||
val attachmentIds = services.attachments.getLatestContractAttachments(contractClassName)
|
||||
// only switchover if we have both signed and unsigned attachments for the given contract class name
|
||||
if (attachmentIds.isNotEmpty() && attachmentIds.size == 2) {
|
||||
val attachmentsToUse = attachmentIds.map {
|
||||
@ -465,7 +465,7 @@ open class TransactionBuilder(
|
||||
require(isReference || constraints.none { it is HashAttachmentConstraint })
|
||||
|
||||
val minimumRequiredContractClassVersion = stateRefs?.map { services.loadContractAttachment(it).contractVersion }?.max() ?: DEFAULT_CORDAPP_VERSION
|
||||
return services.attachments.getContractAttachmentWithHighestContractVersion(contractClassName, minimumRequiredContractClassVersion)
|
||||
return services.attachments.getLatestContractAttachments(contractClassName, minimumRequiredContractClassVersion).firstOrNull()
|
||||
?: throw MissingContractAttachments(states, minimumRequiredContractClassVersion)
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ class TransactionBuilderTest {
|
||||
doReturn(setOf(DummyContract.PROGRAM_ID)).whenever(attachment).allContracts
|
||||
doReturn("app").whenever(attachment).uploader
|
||||
doReturn(emptyList<Party>()).whenever(attachment).signerKeys
|
||||
doReturn(contractAttachmentId).whenever(attachmentStorage)
|
||||
.getContractAttachmentWithHighestContractVersion("net.corda.testing.contracts.DummyContract", DEFAULT_CORDAPP_VERSION)
|
||||
doReturn(listOf(contractAttachmentId)).whenever(attachmentStorage)
|
||||
.getLatestContractAttachments("net.corda.testing.contracts.DummyContract")
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -146,8 +146,8 @@ class TransactionBuilderTest {
|
||||
|
||||
doReturn(attachments).whenever(services).attachments
|
||||
doReturn(signedAttachment).whenever(attachments).openAttachment(contractAttachmentId)
|
||||
doReturn(contractAttachmentId).whenever(attachments)
|
||||
.getContractAttachmentWithHighestContractVersion("net.corda.testing.contracts.DummyContract", DEFAULT_CORDAPP_VERSION)
|
||||
doReturn(listOf(contractAttachmentId)).whenever(attachments)
|
||||
.getLatestContractAttachments("net.corda.testing.contracts.DummyContract")
|
||||
|
||||
val outputState = TransactionState(data = DummyState(), contract = DummyContract.PROGRAM_ID, notary = notary)
|
||||
val builder = TransactionBuilder()
|
||||
|
Reference in New Issue
Block a user