CORDA-3184 - Vault Query API enhancement: strict participants matching (#5524)

* Implementation of exact participant parsing for common query criteria.

* Added more unit tests + fixed a minor bug.

* Additional clean-up.

* Add documentation and changelog entry.

* Revert debug level SQL logging.

* Fix detekt errors.

* Fix docs formatting in code samples.

* Updating baseline (false positives being reported).

* Fix "Name shadowed: subRoot" code quality check.

* Fix API stability checker failures.

* Update baseline.
This commit is contained in:
josecoll 2019-09-27 15:44:04 +01:00 committed by GitHub
parent 6ca4b589e2
commit 7dd6ecf96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 272 additions and 16 deletions

View File

@ -8,6 +8,7 @@ import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateRef import net.corda.core.contracts.StateRef
import net.corda.core.contracts.UniqueIdentifier import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.schemas.StatePersistable import net.corda.core.schemas.StatePersistable
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
@ -82,6 +83,7 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
open val participants: List<AbstractParty>? = null open val participants: List<AbstractParty>? = null
abstract val contractStateTypes: Set<Class<out ContractState>>? abstract val contractStateTypes: Set<Class<out ContractState>>?
open val externalIds: List<UUID> = emptyList() open val externalIds: List<UUID> = emptyList()
open val exactParticipants: List<AbstractParty>? = null
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> { override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
return parser.parseCriteria(this) return parser.parseCriteria(this)
} }
@ -101,8 +103,23 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(), override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
override val constraints: Set<Vault.ConstraintInfo> = emptySet(), override val constraints: Set<Vault.ConstraintInfo> = emptySet(),
override val participants: List<AbstractParty>? = null, override val participants: List<AbstractParty>? = null,
override val externalIds: List<UUID> = emptyList() override val externalIds: List<UUID> = emptyList(),
override val exactParticipants: List<AbstractParty>? = null
) : CommonQueryCriteria() { ) : CommonQueryCriteria() {
@DeprecatedConstructorForDeserialization(version = 7)
constructor(
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
contractStateTypes: Set<Class<out ContractState>>? = null,
stateRefs: List<StateRef>? = null,
notary: List<AbstractParty>? = null,
softLockingCondition: SoftLockingCondition? = null,
timeCondition: TimeCondition? = null,
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
constraints: Set<Vault.ConstraintInfo> = emptySet(),
participants: List<AbstractParty>? = null,
externalIds: List<UUID> = emptyList()
) : this(status, contractStateTypes, stateRefs, notary, softLockingCondition, timeCondition, relevancyStatus, constraintTypes, constraints, participants, externalIds, null)
// V4 constructors. // V4 constructors.
@DeprecatedConstructorForDeserialization(version = 7) @DeprecatedConstructorForDeserialization(version = 7)
constructor( constructor(
@ -162,6 +179,36 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
fun withConstraints(constraints: Set<Vault.ConstraintInfo>): VaultQueryCriteria = copy(constraints = constraints) fun withConstraints(constraints: Set<Vault.ConstraintInfo>): VaultQueryCriteria = copy(constraints = constraints)
fun withParticipants(participants: List<AbstractParty>): VaultQueryCriteria = copy(participants = participants) fun withParticipants(participants: List<AbstractParty>): VaultQueryCriteria = copy(participants = participants)
fun withExternalIds(externalIds: List<UUID>): VaultQueryCriteria = copy(externalIds = externalIds) fun withExternalIds(externalIds: List<UUID>): VaultQueryCriteria = copy(externalIds = externalIds)
fun withExactParticipants(exactParticipants: List<AbstractParty>): VaultQueryCriteria = copy(exactParticipants = exactParticipants)
fun copy(
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
contractStateTypes: Set<Class<out ContractState>>? = null,
stateRefs: List<StateRef>? = null,
notary: List<AbstractParty>? = null,
softLockingCondition: SoftLockingCondition? = null,
timeCondition: TimeCondition? = null,
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
constraints: Set<Vault.ConstraintInfo> = emptySet(),
participants: List<AbstractParty>? = null,
externalIds: List<UUID> = emptyList()
): VaultQueryCriteria {
return VaultQueryCriteria(
status,
contractStateTypes,
stateRefs,
notary,
softLockingCondition,
timeCondition,
relevancyStatus,
constraintTypes,
constraints,
participants,
externalIds,
exactParticipants
)
}
fun copy( fun copy(
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
@ -218,13 +265,24 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
* LinearStateQueryCriteria: provides query by attributes defined in [VaultSchema.VaultLinearState] * LinearStateQueryCriteria: provides query by attributes defined in [VaultSchema.VaultLinearState]
*/ */
data class LinearStateQueryCriteria( data class LinearStateQueryCriteria(
override val participants: List<AbstractParty>?, override val participants: List<AbstractParty>? = null,
val uuid: List<UUID>? = null, val uuid: List<UUID>? = null,
val externalId: List<String>? = null, val externalId: List<String>? = null,
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
override val contractStateTypes: Set<Class<out ContractState>>? = null, override val contractStateTypes: Set<Class<out ContractState>>? = null,
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
override val exactParticipants: List<AbstractParty>?
) : CommonQueryCriteria() { ) : CommonQueryCriteria() {
// V4 c'tor
@DeprecatedConstructorForDeserialization(version = 4)
constructor(
participants: List<AbstractParty>? = null,
uuid: List<UUID>? = null,
externalId: List<String>? = null,
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
contractStateTypes: Set<Class<out ContractState>>? = null,
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
) : this(participants, uuid, externalId, status, contractStateTypes, relevancyStatus, null)
// V3 c'tor // V3 c'tor
@JvmOverloads @JvmOverloads
@DeprecatedConstructorForDeserialization(version = 2) @DeprecatedConstructorForDeserialization(version = 2)
@ -265,6 +323,8 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
fun withStatus(status: Vault.StateStatus): LinearStateQueryCriteria = copy(status = status) fun withStatus(status: Vault.StateStatus): LinearStateQueryCriteria = copy(status = status)
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): LinearStateQueryCriteria = copy(contractStateTypes = contractStateTypes) fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): LinearStateQueryCriteria = copy(contractStateTypes = contractStateTypes)
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): LinearStateQueryCriteria = copy(relevancyStatus = relevancyStatus) fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): LinearStateQueryCriteria = copy(relevancyStatus = relevancyStatus)
fun withExactParticipants(exactParticipants: List<AbstractParty>): LinearStateQueryCriteria =
copy(exactParticipants = exactParticipants)
fun copy( fun copy(
participants: List<AbstractParty>? = this.participants, participants: List<AbstractParty>? = this.participants,
@ -272,6 +332,23 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
externalId: List<String>? = this.externalId, externalId: List<String>? = this.externalId,
status: Vault.StateStatus = this.status, status: Vault.StateStatus = this.status,
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes
): LinearStateQueryCriteria {
return LinearStateQueryCriteria(
participants,
uuid,
externalId,
status,
contractStateTypes
)
}
fun copy(
participants: List<AbstractParty>? = this.participants,
uuid: List<UUID>? = this.uuid,
externalId: List<String>? = this.externalId,
status: Vault.StateStatus = this.status,
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
): LinearStateQueryCriteria { ): LinearStateQueryCriteria {
return LinearStateQueryCriteria( return LinearStateQueryCriteria(
participants, participants,
@ -317,8 +394,21 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
val issuerRef: List<OpaqueBytes>? = null, val issuerRef: List<OpaqueBytes>? = null,
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
override val contractStateTypes: Set<Class<out ContractState>>? = null, override val contractStateTypes: Set<Class<out ContractState>>? = null,
override val relevancyStatus: Vault.RelevancyStatus override val relevancyStatus: Vault.RelevancyStatus,
override val exactParticipants: List<AbstractParty>? = null
) : CommonQueryCriteria() { ) : CommonQueryCriteria() {
// V4 c'tor
@DeprecatedConstructorForDeserialization(version = 1)
constructor(
participants: List<AbstractParty>? = null,
owner: List<AbstractParty>? = null,
quantity: ColumnPredicate<Long>? = null,
issuer: List<AbstractParty>? = null,
issuerRef: List<OpaqueBytes>? = null,
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
contractStateTypes: Set<Class<out ContractState>>? = null,
relevancyStatus: Vault.RelevancyStatus
) : this(participants, owner, quantity, issuer, issuerRef, status, contractStateTypes, relevancyStatus, null)
@JvmOverloads @JvmOverloads
@DeprecatedConstructorForDeserialization(version = 1) @DeprecatedConstructorForDeserialization(version = 1)
constructor( constructor(
@ -344,6 +434,30 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
fun withStatus(status: Vault.StateStatus): FungibleAssetQueryCriteria = copy(status = status) fun withStatus(status: Vault.StateStatus): FungibleAssetQueryCriteria = copy(status = status)
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): FungibleAssetQueryCriteria = copy(contractStateTypes = contractStateTypes) fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): FungibleAssetQueryCriteria = copy(contractStateTypes = contractStateTypes)
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): FungibleAssetQueryCriteria = copy(relevancyStatus = relevancyStatus) fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): FungibleAssetQueryCriteria = copy(relevancyStatus = relevancyStatus)
fun withExactParticipants(exactParticipants: List<AbstractParty>): FungibleAssetQueryCriteria
= copy(exactParticipants = exactParticipants)
fun copy(
participants: List<AbstractParty>? = this.participants,
owner: List<AbstractParty>? = this.owner,
quantity: ColumnPredicate<Long>? = this.quantity,
issuer: List<AbstractParty>? = this.issuer,
issuerRef: List<OpaqueBytes>? = this.issuerRef,
status: Vault.StateStatus = this.status,
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
): FungibleAssetQueryCriteria {
return FungibleAssetQueryCriteria(
participants,
owner,
quantity,
issuer,
issuerRef,
status,
contractStateTypes,
relevancyStatus
)
}
fun copy( fun copy(
participants: List<AbstractParty>? = this.participants, participants: List<AbstractParty>? = this.participants,

View File

@ -755,6 +755,7 @@
<ID>LargeClass:PropertyTest.kt$PropertyTest</ID> <ID>LargeClass:PropertyTest.kt$PropertyTest</ID>
<ID>LargeClass:PropertyValidationTest.kt$PropertyValidationTest</ID> <ID>LargeClass:PropertyValidationTest.kt$PropertyValidationTest</ID>
<ID>LargeClass:ProtonWrapperTests.kt$ProtonWrapperTests</ID> <ID>LargeClass:ProtonWrapperTests.kt$ProtonWrapperTests</ID>
<ID>LargeClass:QueryCriteria.kt$QueryCriteria$VaultQueryCriteria : CommonQueryCriteria</ID>
<ID>LargeClass:QueryCriteriaUtils.kt$Builder</ID> <ID>LargeClass:QueryCriteriaUtils.kt$Builder</ID>
<ID>LargeClass:RPCClientProxyHandler.kt$RPCClientProxyHandler : InvocationHandler</ID> <ID>LargeClass:RPCClientProxyHandler.kt$RPCClientProxyHandler : InvocationHandler</ID>
<ID>LargeClass:RPCDriver.kt$RPCDriverDSL : InternalDriverDSL</ID> <ID>LargeClass:RPCDriver.kt$RPCDriverDSL : InternalDriverDSL</ID>
@ -790,6 +791,7 @@
<ID>LargeClass:X509UtilitiesTest.kt$X509UtilitiesTest</ID> <ID>LargeClass:X509UtilitiesTest.kt$X509UtilitiesTest</ID>
<ID>LongMethod:EdDSATests.kt$EdDSATests$@Test fun `PureEdDSA Ed25519 test vectors`()</ID> <ID>LongMethod:EdDSATests.kt$EdDSATests$@Test fun `PureEdDSA Ed25519 test vectors`()</ID>
<ID>LongMethod:FlowCookbook.kt$InitiatorFlow$@Suppress("RemoveExplicitTypeArguments") @Suspendable override fun call()</ID> <ID>LongMethod:FlowCookbook.kt$InitiatorFlow$@Suppress("RemoveExplicitTypeArguments") @Suspendable override fun call()</ID>
<ID>LongMethod:HibernateQueryCriteriaParser.kt$HibernateQueryCriteriaParser$override fun parseCriteria(criteria: CommonQueryCriteria): Collection&lt;Predicate&gt;</ID>
<ID>LongMethod:IRSTests.kt$fun createDummyIRS(irsSelect: Int): InterestRateSwap.State</ID> <ID>LongMethod:IRSTests.kt$fun createDummyIRS(irsSelect: Int): InterestRateSwap.State</ID>
<ID>LongMethod:RpcReconnectTests.kt$RpcReconnectTests$ @Test fun `test that the RPC client is able to reconnect and proceed after node failure, restart, or connection reset`()</ID> <ID>LongMethod:RpcReconnectTests.kt$RpcReconnectTests$ @Test fun `test that the RPC client is able to reconnect and proceed after node failure, restart, or connection reset`()</ID>
<ID>LongParameterList:AMQPSerializer.kt$AMQPSerializer$(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int = 0)</ID> <ID>LongParameterList:AMQPSerializer.kt$AMQPSerializer$(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int = 0)</ID>
@ -870,7 +872,10 @@
<ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( arguments: List&lt;String&gt;, classPath: List&lt;String&gt; = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List&lt;String&gt; = emptyList(), maximumHeapSize: String? = null )</ID> <ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( arguments: List&lt;String&gt;, classPath: List&lt;String&gt; = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List&lt;String&gt; = emptyList(), maximumHeapSize: String? = null )</ID>
<ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( className: String, arguments: List&lt;String&gt;, classPath: List&lt;String&gt; = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List&lt;String&gt; = emptyList(), maximumHeapSize: String? = null )</ID> <ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( className: String, arguments: List&lt;String&gt;, classPath: List&lt;String&gt; = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List&lt;String&gt; = emptyList(), maximumHeapSize: String? = null )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.FungibleAssetQueryCriteria$( participants: List&lt;AbstractParty&gt;? = this.participants, owner: List&lt;AbstractParty&gt;? = this.owner, quantity: ColumnPredicate&lt;Long&gt;? = this.quantity, issuer: List&lt;AbstractParty&gt;? = this.issuer, issuerRef: List&lt;OpaqueBytes&gt;? = this.issuerRef, status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes )</ID> <ID>LongParameterList:QueryCriteria.kt$QueryCriteria.FungibleAssetQueryCriteria$( participants: List&lt;AbstractParty&gt;? = this.participants, owner: List&lt;AbstractParty&gt;? = this.owner, quantity: ColumnPredicate&lt;Long&gt;? = this.quantity, issuer: List&lt;AbstractParty&gt;? = this.issuer, issuerRef: List&lt;OpaqueBytes&gt;? = this.issuerRef, status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.FungibleAssetQueryCriteria$( participants: List&lt;AbstractParty&gt;? = this.participants, owner: List&lt;AbstractParty&gt;? = this.owner, quantity: ColumnPredicate&lt;Long&gt;? = this.quantity, issuer: List&lt;AbstractParty&gt;? = this.issuer, issuerRef: List&lt;OpaqueBytes&gt;? = this.issuerRef, status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes, relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.LinearStateQueryCriteria$( participants: List&lt;AbstractParty&gt;? = this.participants, uuid: List&lt;UUID&gt;? = this.uuid, externalId: List&lt;String&gt;? = this.externalId, status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes, relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null )</ID> <ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null, externalIds: List&lt;UUID&gt; = emptyList() )</ID>
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes, stateRefs: List&lt;StateRef&gt;? = this.stateRefs, notary: List&lt;AbstractParty&gt;? = this.notary, softLockingCondition: SoftLockingCondition? = this.softLockingCondition, timeCondition: TimeCondition? = this.timeCondition )</ID> <ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = this.status, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = this.contractStateTypes, stateRefs: List&lt;StateRef&gt;? = this.stateRefs, notary: List&lt;AbstractParty&gt;? = this.notary, softLockingCondition: SoftLockingCondition? = this.softLockingCondition, timeCondition: TimeCondition? = this.timeCondition )</ID>
<ID>LongParameterList:RPCClient.kt$RPCClient$( rpcOpsClass: Class&lt;I&gt;, username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null, targetLegalIdentity: CordaX500Name? = null )</ID> <ID>LongParameterList:RPCClient.kt$RPCClient$( rpcOpsClass: Class&lt;I&gt;, username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null, targetLegalIdentity: CordaX500Name? = null )</ID>
<ID>LongParameterList:RPCDriver.kt$( isDebug: Boolean = false, driverDirectory: Path = Paths.get("build") / "rpc-driver" / getTimestampAsDirectoryName(), portAllocation: PortAllocation = globalPortAllocation, debugPortAllocation: PortAllocation = globalDebugPortAllocation, systemProperties: Map&lt;String, String&gt; = emptyMap(), useTestClock: Boolean = false, startNodesInProcess: Boolean = false, waitForNodesToFinish: Boolean = false, extraCordappPackagesToScan: List&lt;String&gt; = emptyList(), notarySpecs: List&lt;NotarySpec&gt; = emptyList(), externalTrace: Trace? = null, @Suppress("DEPRECATION") jmxPolicy: JmxPolicy = JmxPolicy(), networkParameters: NetworkParameters = testNetworkParameters(), notaryCustomOverrides: Map&lt;String, Any?&gt; = emptyMap(), inMemoryDB: Boolean = true, cordappsForAllNodes: Collection&lt;TestCordappInternal&gt;? = null, dsl: RPCDriverDSL.() -&gt; A )</ID> <ID>LongParameterList:RPCDriver.kt$( isDebug: Boolean = false, driverDirectory: Path = Paths.get("build") / "rpc-driver" / getTimestampAsDirectoryName(), portAllocation: PortAllocation = globalPortAllocation, debugPortAllocation: PortAllocation = globalDebugPortAllocation, systemProperties: Map&lt;String, String&gt; = emptyMap(), useTestClock: Boolean = false, startNodesInProcess: Boolean = false, waitForNodesToFinish: Boolean = false, extraCordappPackagesToScan: List&lt;String&gt; = emptyList(), notarySpecs: List&lt;NotarySpec&gt; = emptyList(), externalTrace: Trace? = null, @Suppress("DEPRECATION") jmxPolicy: JmxPolicy = JmxPolicy(), networkParameters: NetworkParameters = testNetworkParameters(), notaryCustomOverrides: Map&lt;String, Any?&gt; = emptyMap(), inMemoryDB: Boolean = true, cordappsForAllNodes: Collection&lt;TestCordappInternal&gt;? = null, dsl: RPCDriverDSL.() -&gt; A )</ID>
@ -4459,6 +4464,7 @@
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withContractStateTypes(contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;): VaultCustomQueryCriteria&lt;L&gt;</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withContractStateTypes(contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;): VaultCustomQueryCriteria&lt;L&gt;</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): VaultCustomQueryCriteria&lt;L&gt;</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): VaultCustomQueryCriteria&lt;L&gt;</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null )</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null )</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;? = null, stateRefs: List&lt;StateRef&gt;? = null, notary: List&lt;AbstractParty&gt;? = null, softLockingCondition: SoftLockingCondition? = null, timeCondition: TimeCondition? = null, relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL, constraintTypes: Set&lt;Vault.ConstraintInfo.Type&gt; = emptySet(), constraints: Set&lt;Vault.ConstraintInfo&gt; = emptySet(), participants: List&lt;AbstractParty&gt;? = null, externalIds: List&lt;UUID&gt; = emptyList() )</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 2) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?) : this(status, contractStateTypes, participants = null)</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 2) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?) : this(status, contractStateTypes, participants = null)</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 4) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?, stateRefs: List&lt;StateRef&gt;?, notary: List&lt;AbstractParty&gt;?) : this( status, contractStateTypes, stateRefs, notary, participants = null )</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 4) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?, stateRefs: List&lt;StateRef&gt;?, notary: List&lt;AbstractParty&gt;?) : this( status, contractStateTypes, stateRefs, notary, participants = null )</ID>
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 5) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?, stateRefs: List&lt;StateRef&gt;?, notary: List&lt;AbstractParty&gt;?, softLockingCondition: SoftLockingCondition?) : this( status, contractStateTypes, stateRefs, notary, softLockingCondition, participants = null )</ID> <ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 5) constructor(status: Vault.StateStatus, contractStateTypes: Set&lt;Class&lt;out ContractState&gt;&gt;?, stateRefs: List&lt;StateRef&gt;?, notary: List&lt;AbstractParty&gt;?, softLockingCondition: SoftLockingCondition?) : this( status, contractStateTypes, stateRefs, notary, softLockingCondition, participants = null )</ID>
@ -5839,6 +5845,7 @@
<ID>TooManyFunctions:PropertyValidationTest.kt$PropertyValidationTest</ID> <ID>TooManyFunctions:PropertyValidationTest.kt$PropertyValidationTest</ID>
<ID>TooManyFunctions:ProtonWrapperTests.kt$ProtonWrapperTests</ID> <ID>TooManyFunctions:ProtonWrapperTests.kt$ProtonWrapperTests</ID>
<ID>TooManyFunctions:PublicKeyToOwningIdentityCacheImplTest.kt$PublicKeyToOwningIdentityCacheImplTest</ID> <ID>TooManyFunctions:PublicKeyToOwningIdentityCacheImplTest.kt$PublicKeyToOwningIdentityCacheImplTest</ID>
<ID>TooManyFunctions:QueryCriteria.kt$QueryCriteria$FungibleAssetQueryCriteria : CommonQueryCriteria</ID>
<ID>TooManyFunctions:QueryCriteria.kt$QueryCriteria$VaultQueryCriteria : CommonQueryCriteria</ID> <ID>TooManyFunctions:QueryCriteria.kt$QueryCriteria$VaultQueryCriteria : CommonQueryCriteria</ID>
<ID>TooManyFunctions:QueryCriteriaUtils.kt$Builder</ID> <ID>TooManyFunctions:QueryCriteriaUtils.kt$Builder</ID>
<ID>TooManyFunctions:RPCApi.kt$net.corda.nodeapi.RPCApi.kt</ID> <ID>TooManyFunctions:RPCApi.kt$net.corda.nodeapi.RPCApi.kt</ID>

View File

@ -86,7 +86,8 @@ There are four implementations of this interface which can be chained together t
1. ``VaultQueryCriteria`` provides filterable criteria on attributes within the Vault states table: status (UNCONSUMED, 1. ``VaultQueryCriteria`` provides filterable criteria on attributes within the Vault states table: status (UNCONSUMED,
CONSUMED), state reference(s), contract state type(s), notaries, soft locked states, timestamps (RECORDED, CONSUMED), CONSUMED), state reference(s), contract state type(s), notaries, soft locked states, timestamps (RECORDED, CONSUMED),
state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT). state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT),
participants (exact or any match).
.. note:: Sensible defaults are defined for frequently used attributes (status = UNCONSUMED, always include soft .. note:: Sensible defaults are defined for frequently used attributes (status = UNCONSUMED, always include soft
locked states). locked states).
@ -94,7 +95,7 @@ There are four implementations of this interface which can be chained together t
2. ``FungibleAssetQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core 2. ``FungibleAssetQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core
``FungibleAsset`` contract state interface, used to represent assets that are fungible, countable and issued by a ``FungibleAsset`` contract state interface, used to represent assets that are fungible, countable and issued by a
specific party (eg. ``Cash.State`` and ``CommodityContract.State`` in the Corda finance module). Filterable specific party (eg. ``Cash.State`` and ``CommodityContract.State`` in the Corda finance module). Filterable
attributes include: participants(s), owner(s), quantity, issuer party(s) and issuer reference(s). attributes include: participants (exact or any match), owner(s), quantity, issuer party(s) and issuer reference(s).
.. note:: All contract states that extend the ``FungibleAsset`` now automatically persist that interfaces common .. note:: All contract states that extend the ``FungibleAsset`` now automatically persist that interfaces common
state attributes to the **vault_fungible_states** table. state attributes to the **vault_fungible_states** table.
@ -102,7 +103,7 @@ There are four implementations of this interface which can be chained together t
3. ``LinearStateQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core ``LinearState`` 3. ``LinearStateQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core ``LinearState``
and ``DealState`` contract state interfaces, used to represent entities that continuously supersede themselves, all and ``DealState`` contract state interfaces, used to represent entities that continuously supersede themselves, all
of which share the same ``linearId`` (e.g. trade entity states such as the ``IRSState`` defined in the SIMM of which share the same ``linearId`` (e.g. trade entity states such as the ``IRSState`` defined in the SIMM
valuation demo). Filterable attributes include: participant(s), linearId(s), uuid(s), and externalId(s). valuation demo). Filterable attributes include: participants (exact or any match), linearId(s), uuid(s), and externalId(s).
.. note:: All contract states that extend ``LinearState`` or ``DealState`` now automatically persist those .. note:: All contract states that extend ``LinearState`` or ``DealState`` now automatically persist those
interfaces common state attributes to the **vault_linear_states** table. interfaces common state attributes to the **vault_linear_states** table.
@ -292,7 +293,7 @@ Query for unconsumed states for a given notary:
:end-before: DOCEND VaultQueryExample4 :end-before: DOCEND VaultQueryExample4
:dedent: 12 :dedent: 12
Query for unconsumed states for a given set of participants: Query for unconsumed states for a given set of participants (matches any state that contains at least one of the specified participants):
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt .. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
:language: kotlin :language: kotlin
@ -300,6 +301,14 @@ Query for unconsumed states for a given set of participants:
:end-before: DOCEND VaultQueryExample5 :end-before: DOCEND VaultQueryExample5
:dedent: 12 :dedent: 12
Query for unconsumed states for a given set of participants (exactly matches only states that contain all specified participants):
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
:language: kotlin
:start-after: DOCSTART VaultQueryExample51
:end-before: DOCEND VaultQueryExample51
:dedent: 12
Query for unconsumed states recorded between two time intervals: Query for unconsumed states recorded between two time intervals:
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt .. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
@ -364,7 +373,7 @@ Query for unconsumed deal states with deals references:
:end-before: DOCEND VaultQueryExample10 :end-before: DOCEND VaultQueryExample10
:dedent: 12 :dedent: 12
Query for unconsumed deal states with deals parties: Query for unconsumed deal states with deals parties (any match):
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt .. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
:language: kotlin :language: kotlin
@ -372,6 +381,14 @@ Query for unconsumed deal states with deals parties:
:end-before: DOCEND VaultQueryExample11 :end-before: DOCEND VaultQueryExample11
:dedent: 12 :dedent: 12
Query for unconsumed deal states with deals parties (exact match):
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
:language: kotlin
:start-after: DOCSTART VaultQueryExample52
:end-before: DOCEND VaultQueryExample52
:dedent: 12
Query for only relevant linear states in the vault: Query for only relevant linear states in the vault:
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt .. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt

View File

@ -8,6 +8,8 @@ Unreleased
---------- ----------
* Moved and renamed the testing web server to the ``testing`` subproject. Also renamed the published artifact to ``corda-testserver.jar``. * Moved and renamed the testing web server to the ``testing`` subproject. Also renamed the published artifact to ``corda-testserver.jar``.
* New Vault Query criteria to specify exact matches for specified participants.
* Support for Java 11 (compatibility mode). Please read https://github.com/corda/corda/pull/5356. * Support for Java 11 (compatibility mode). Please read https://github.com/corda/corda/pull/5356.
* Removed the RPC exception privacy feature. Previously, in production mode, the exceptions thrown on the node were stripped of all content * Removed the RPC exception privacy feature. Previously, in production mode, the exceptions thrown on the node were stripped of all content

View File

@ -471,8 +471,12 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs))) predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
} }
if (criteria.participants != null && criteria.exactParticipants != null)
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) and exactParticipants " +
"(${criteria.exactParticipants}).")
// Participants. // Participants.
criteria.participants?.let { if (criteria.participants != null || criteria.exactParticipants != null) {
// Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate) // Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate)
val statePartyToFungibleStatesJoin = criteriaBuilder.and( val statePartyToFungibleStatesJoin = criteriaBuilder.and(
criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"), criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"),
@ -508,8 +512,12 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds))) predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
} }
if (criteria.participants != null && criteria.exactParticipants != null)
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) " +
"and exactParticipants (${criteria.exactParticipants}).")
// Participants. // Participants.
criteria.participants?.let { if (criteria.participants != null || criteria.exactParticipants != null) {
// Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate) // Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate)
val statePartyToLinearStatesJoin = criteriaBuilder.and( val statePartyToLinearStatesJoin = criteriaBuilder.and(
criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"), criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"),
@ -702,6 +710,38 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
} }
} }
// Exact participants
// Requires a tricky SQL query to ensure *only* exact matches are selected (eg. a transaction cannot have more nor less than the
// exact participants specified in the query criteria).
criteria.exactParticipants?.let {
val exactParticipants = criteria.exactParticipants!!
// obtain all transactions where other participants are not present
val subQueryNotExists = criteriaQuery.subquery(Tuple::class.java)
val subRoot = subQueryNotExists.from(VaultSchemaV1.PersistentParty::class.java)
subQueryNotExists.select(subRoot.get("x500Name"))
subQueryNotExists.where(criteriaBuilder.and(
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
subRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
criteriaBuilder.not(subRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(exactParticipants)))
val subQueryNotExistsPredicate = criteriaBuilder.and(criteriaBuilder.not(criteriaBuilder.exists(subQueryNotExists)))
constraintPredicates.add(subQueryNotExistsPredicate)
// join with transactions for each matching participant (only required where more than one)
if (exactParticipants.size > 1)
exactParticipants.forEach { participant ->
val subQueryExists = criteriaQuery.subquery(Tuple::class.java)
val subRootExists = subQueryExists.from(VaultSchemaV1.PersistentParty::class.java)
subQueryExists.select(subRootExists.get("x500Name"))
subQueryExists.where(criteriaBuilder.and(
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
subRootExists.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
criteriaBuilder.equal(subRootExists.get<VaultSchemaV1.PersistentParty>("x500Name"), participant))
val subQueryExistsPredicate = criteriaBuilder.and(criteriaBuilder.exists(subQueryExists))
constraintPredicates.add(subQueryExistsPredicate)
}
}
return emptySet() return emptySet()
} }

View File

@ -241,6 +241,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP)) val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP))
val results = vaultService.queryBy<ContractState>(criteria) val results = vaultService.queryBy<ContractState>(criteria)
assertThat(results.states).hasSize(1) assertThat(results.states).hasSize(1)
// same query using strict participant matching
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(BIG_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
} }
} }
@ -254,6 +259,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP)) val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP))
val results = vaultService.queryBy<ContractState>(criteria) val results = vaultService.queryBy<ContractState>(criteria)
assertThat(results.states).hasSize(2) assertThat(results.states).hasSize(2)
// same query using strict participant matching
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(MEGA_CORP, BIG_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(1)
} }
} }
@ -795,10 +805,48 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY) identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
vaultFiller.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP)) vaultFiller.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
vaultFiller.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP)) vaultFiller.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP)) vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(MEGA_CORP))
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP))
val criteria = LinearStateQueryCriteria(participants = listOf(MEGA_CORP))
val results = vaultService.queryBy<ContractState>(criteria) val results = vaultService.queryBy<ContractState>(criteria)
assertThat(results.states).hasSize(3) assertThat(results.states).hasSize(5)
// same query using strict participant matching
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(2)
}
}
@Test
fun `unconsumed dummy states for exact single participant`() {
database.transaction {
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP))
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP)) // exact match
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(1)
}
}
@Test
fun `unconsumed dummy states for exact two participants`() {
database.transaction {
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) // exact match
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP))
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(1)
// same query using strict participant matching (unordered list of participants)
val strictCriteriaUnordered = VaultQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
assertThat(strictResultsUnordered.states).hasSize(1)
} }
} }
@ -813,8 +861,19 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP)) val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP))
val results = vaultService.queryBy<ContractState>(criteria) val results = vaultService.queryBy<ContractState>(criteria)
// DOCEND VaultQueryExample5 // DOCEND VaultQueryExample5
assertThat(results.states).hasSize(3) assertThat(results.states).hasSize(3)
// same query using strict participant matching
// DOCSTART VaultQueryExample51
val strictCriteria = LinearStateQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
// DOCEND VaultQueryExample51
assertThat(strictResults.states).hasSize(1)
// same query using strict participant matching (unordered list of participants)
val strictCriteriaUnordered = LinearStateQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
assertThat(strictResultsUnordered.states).hasSize(1)
} }
} }
@ -1959,6 +2018,13 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
// DOCEND VaultQueryExample11 // DOCEND VaultQueryExample11
assertThat(results.states).hasSize(1) assertThat(results.states).hasSize(1)
// same query using strict participant matching
// DOCSTART VaultQueryExample52
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(parties)
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
// DOCEND VaultQueryExample52
assertThat(strictResults.states).hasSize(0) // node identity included (MEGA_CORP)
} }
} }
@ -2352,6 +2418,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
assertThat(results.states).hasSize(1) assertThat(results.states).hasSize(1)
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1") assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
// same query using strict participant matching
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(ALICE))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
} }
} }
@ -2369,6 +2440,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
assertThat(results.states).hasSize(1) assertThat(results.states).hasSize(1)
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1") assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
// same query using strict participant matching
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP, ALICE, BOB, CHARLIE))
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
assertThat(strictResults.states).hasSize(1)
} }
} }
@ -2401,7 +2477,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
} }
@Test @Test
fun `composite query for fungible and linear states for multiple participants`() { fun `composite query for fungible, linear and dummy states for multiple participants`() {
database.transaction { database.transaction {
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY) identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY) identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)