diff --git a/core/src/main/kotlin/net/corda/core/node/services/VaultService.kt b/core/src/main/kotlin/net/corda/core/node/services/VaultService.kt index 1913e6bf84..b73673c3a3 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/VaultService.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/VaultService.kt @@ -68,7 +68,7 @@ class Vault(val states: Iterable>) { * other transactions observed, then the changes are observed "net" of those. */ @CordaSerializable - data class Update @JvmOverloads constructor( + data class Update constructor( val consumed: Set>, val produced: Set>, val flowId: UUID? = null, @@ -78,8 +78,20 @@ class Vault(val states: Iterable>) { * differently. */ val type: UpdateType = UpdateType.GENERAL, - val references: Set> = emptySet() + val references: Set> = emptySet(), + val consumingTxIds: Map = emptyMap() ) { + @JvmOverloads constructor( consumed: Set>, + produced: Set>, + flowId: UUID? = null, + /** + * Specifies the type of update, currently supported types are general and, contract upgrade and notary change. + * Notary change transactions only modify the notary field on states, and potentially need to be handled + * differently. + */ + type: UpdateType = UpdateType.GENERAL, + references: Set> = emptySet()) : this(consumed, produced, flowId, type, references, consumingTxIds = emptyMap()) + /** Checks whether the update contains a state of the specified type. */ inline fun containsType() = consumed.any { it.state.data is T } || produced.any { it.state.data is T } || references.any { it.state.data is T } @@ -105,7 +117,7 @@ class Vault(val states: Iterable>) { val combinedConsumed = consumed + (rhs.consumed - produced) // The ordering below matters to preserve ordering of consumed/produced Sets when they are insertion order dependent implementations. val combinedProduced = produced.filter { it !in rhs.consumed }.toSet() + rhs.produced - return copy(consumed = combinedConsumed, produced = combinedProduced, references = references + rhs.references) + return copy(consumed = combinedConsumed, produced = combinedProduced, references = references + rhs.references, consumingTxIds = consumingTxIds + rhs.consumingTxIds) } override fun toString(): String { @@ -138,6 +150,16 @@ class Vault(val states: Iterable>) { return Update(consumed, produced, flowId, type, references) } + /** Additional copy method to maintain backwards compatibility. */ + fun copy( + consumed: Set>, + produced: Set>, + flowId: UUID? = null, + type: UpdateType = UpdateType.GENERAL, + references: Set> = emptySet() + ): Update { + return Update(consumed, produced, flowId, type, references, consumingTxIds) + } } @CordaSerializable diff --git a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt index ec4984ea68..cca094eb34 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt @@ -231,6 +231,7 @@ class NodeVaultService( if (stateStatus != Vault.StateStatus.CONSUMED) { stateStatus = Vault.StateStatus.CONSUMED consumedTime = clock.instant() + consumingTxId = update.consumingTxIds[stateRef]?.toString() ?: "" // remove lock (if held) if (lockId != null) { lockId = null @@ -370,8 +371,8 @@ class NodeVaultService( } } } - - return Vault.Update(consumedStates.toSet(), ourNewStates.toSet(), references = newReferenceStateAndRefs.toSet()) + val consumedTxIds = consumedStates.associate { Pair(it.ref, tx.id) } + return Vault.Update(consumedStates.toSet(), ourNewStates.toSet(), references = newReferenceStateAndRefs.toSet(), consumingTxIds = consumedTxIds) } fun resolveAndMakeUpdate(tx: CoreTransaction): Vault.Update? { diff --git a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt index 09c71fe1f7..fc7fc9f9db 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt @@ -91,7 +91,11 @@ object VaultSchemaV1 : MappedSchema( /** associated constraint type data (if any) */ @Column(name = "constraint_data", length = MAX_CONSTRAINT_DATA_SIZE, nullable = true) @Type(type = "corda-wrapper-binary") - var constraintData: ByteArray? = null + var constraintData: ByteArray? = null, + + /** consuming transaction */ + @Column(name = "consuming_tx_id", length = 144, nullable = false) + var consumingTxId: String = "" ) : PersistentState() @Entity diff --git a/node/src/main/resources/migration/vault-schema.changelog-master.xml b/node/src/main/resources/migration/vault-schema.changelog-master.xml index 44684647fa..8fea107366 100644 --- a/node/src/main/resources/migration/vault-schema.changelog-master.xml +++ b/node/src/main/resources/migration/vault-schema.changelog-master.xml @@ -13,4 +13,5 @@ +