Updated samples and demos to use new Vault Query service. (#924)

* Updated all sample code to use new Vault Query service APIs.

* Fix broken Unit test.

* Added missing transaction boundary.

* Fix broken ScheduledFlow test (caused by assertion on non-ordered collection)

* Remove redundant negative test (as new Vault Query no longer returns iterators).

* Whitespace formatting fixed following PR review from SA.

* Force query to specify a PAGE SIZE equivalent to total states to be exited (RP review comment).

* Use single (and fail fast) instead of first - when only expecting a single result.

* Demonstrate paging and sorting; failfast on single expected result.

* Enhancement: added Sorting by CommonStateAttribute (StateRef txnId and index)

* Fix: incorrect total states count.

* Fixed incorrect total states counting.

* Remove redundant filter (UNCONSUMED).

* Updated tutorial code and associated documentation (building transactions).

* Updated all vaultAndUpdates to vault[Track|Query]By.

* Temporary disable failing Vault Query tests (awaiting pagination PR fix).

* Rebase from master to pick up pagination changes/fix.

* Fixed criteria filter on track.

* Cleanup redundant print output.

* Refactor to extract common function for Vault Query paging and sorting.

* Identified problem in SimmValuation demo failing test caused by query by single participant in participants list (not yet supported in VaultQuery criteria).

* Minor fixes following rebase from master.

* Minor updates following rebase.

* Removed redundant import.

* Fixed type casting error.

* Minor fixes following rebase from master.

* VQ Fix - applied in other PR.

* Removed duplication after rebase and minor fix to failing smoke test.
This commit is contained in:
josecoll 2017-08-03 11:47:15 +01:00 committed by GitHub
parent 73528d287d
commit 64ba8d3a88
33 changed files with 284 additions and 286 deletions

View File

@ -5,15 +5,13 @@ import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.CordaRPCClientConfiguration
import net.corda.core.contracts.ContractState
import net.corda.core.flows.StateMachineRunId
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.StateMachineInfo
import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.core.messaging.StateMachineUpdate
import net.corda.core.messaging.*
import net.corda.core.node.services.NetworkMapCache.MapChange
import net.corda.core.node.services.Vault
import net.corda.core.node.services.vault.*
import net.corda.core.utilities.seconds
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.seconds
import rx.Observable
import rx.subjects.PublishSubject
@ -84,9 +82,10 @@ class NodeMonitorModel {
val currentStateMachines = stateMachines.map { StateMachineUpdate.Added(it) }
stateMachineUpdates.startWith(currentStateMachines).subscribe(stateMachineUpdatesSubject)
// Vault updates
val (vault, vaultUpdates) = proxy.vaultAndUpdates()
val initialVaultUpdate = Vault.Update(setOf(), vault.toSet())
// Vault snapshot (force single page load with MAX_PAGE_SIZE) + updates
val (vaultSnapshot, vaultUpdates) = proxy.vaultTrackBy<ContractState>(QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL),
PageSpecification(DEFAULT_PAGE_NUM, MAX_PAGE_SIZE))
val initialVaultUpdate = Vault.Update(setOf(), vaultSnapshot.states.toSet())
vaultUpdates.startWith(initialVaultUpdate).subscribe(vaultUpdatesSubject)
// Transactions

View File

@ -135,33 +135,10 @@ class StandaloneCordaRPClientTest {
assertEquals(1, updateCount.get())
}
@Test
fun `test vault`() {
val (vault, vaultUpdates) = rpcProxy.vaultAndUpdates()
assertEquals(0, vault.size)
val updateCount = AtomicInteger(0)
vaultUpdates.subscribe { update ->
log.info("Vault>> FlowId=${update.flowId}")
updateCount.incrementAndGet()
}
// Now issue some cash
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNode.legalIdentity, notaryNode.notaryIdentity)
.returnValue.getOrThrow(timeout)
assertNotEquals(0, updateCount.get())
// Check that this cash exists in the vault
val cashState = rpcProxy.vaultQueryBy<Cash.State>(QueryCriteria.FungibleAssetQueryCriteria()).states.single()
log.info("Cash State: $cashState")
assertEquals(629.POUNDS, cashState.state.data.amount.withoutIssuer())
}
@Test
fun `test vault track by`() {
val (vault, vaultUpdates) = rpcProxy.vaultTrackBy<Cash.State>()
assertEquals(0, vault.states.size)
val (vault, vaultUpdates) = rpcProxy.vaultTrackBy<Cash.State>(paging = PageSpecification(DEFAULT_PAGE_NUM))
assertEquals(0, vault.totalStatesAvailable)
val updateCount = AtomicInteger(0)
vaultUpdates.subscribe { update ->

View File

@ -9,11 +9,11 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.node.services.unconsumedStates
import net.corda.core.node.services.queryBy
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.internal.Emoji
import net.corda.core.utilities.OpaqueBytes
import net.corda.flows.CashIssueFlow
import net.corda.node.internal.CordaRPCOpsImpl
import net.corda.node.services.startFlowPermission
@ -178,14 +178,14 @@ class ContractUpgradeFlowTest {
mockNet.runNetwork()
val stx = result.getOrThrow().stx
val stateAndRef = stx.tx.outRef<Cash.State>(0)
val baseState = a.database.transaction { a.services.vaultService.unconsumedStates<ContractState>().single() }
val baseState = a.database.transaction { a.services.vaultQueryService.queryBy<ContractState>().states.single() }
assertTrue(baseState.state.data is Cash.State, "Contract state is old version.")
// Starts contract upgrade flow.
val upgradeResult = a.services.startFlow(ContractUpgradeFlow(stateAndRef, CashV2::class.java)).resultFuture
mockNet.runNetwork()
upgradeResult.getOrThrow()
// Get contract state from the vault.
val firstState = a.database.transaction { a.services.vaultService.unconsumedStates<ContractState>().single() }
val firstState = a.database.transaction { a.services.vaultQueryService.queryBy<ContractState>().states.single() }
assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.")
assertEquals(Amount(1000000, USD).`issued by`(a.info.legalIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
assertEquals<Collection<AbstractParty>>(listOf(a.info.legalIdentity), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.")

View File

@ -7,6 +7,7 @@ import net.corda.core.contracts.ContractState
import net.corda.core.contracts.DOLLARS
import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultTrackBy
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.Vault
import net.corda.core.node.services.vault.QueryCriteria
@ -59,9 +60,8 @@ class IntegrationTestingTutorial {
// END 2
// START 3
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
val (_, bobVaultUpdates) = bobProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
val (_, aliceVaultUpdates) = aliceProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
val bobVaultUpdates = bobProxy.vaultTrackBy<Cash.State>().updates
val aliceVaultUpdates = aliceProxy.vaultTrackBy<Cash.State>().updates
// END 3
// START 4

View File

@ -6,6 +6,7 @@ import net.corda.core.contracts.Amount
import net.corda.core.contracts.USD
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.node.services.ServiceInfo
import net.corda.core.serialization.CordaSerializable
@ -105,10 +106,10 @@ fun main(args: Array<String>) {
// START 6
fun generateTransactions(proxy: CordaRPCOps) {
val (vault, vaultUpdates) = proxy.vaultAndUpdates()
vaultUpdates.notUsed()
val vault = proxy.vaultQueryBy<Cash.State>().states
var ownedQuantity = vault.fold(0L) { sum, state ->
sum + (state.state.data as Cash.State).amount.quantity
sum + state.state.data.amount.quantity
}
val issueRef = OpaqueBytes.of(0)
val (parties, partyUpdates) = proxy.networkMapFeed()

View File

@ -10,13 +10,14 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.builder
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.unwrap
import net.corda.schemas.CashSchemaV1
import java.util.*
@CordaSerializable
@ -36,18 +37,18 @@ private data class FxResponse(val inputs: List<StateAndRef<Cash.State>>,
private fun gatherOurInputs(serviceHub: ServiceHub,
amountRequired: Amount<Issued<Currency>>,
notary: Party?): Pair<List<StateAndRef<Cash.State>>, Long> {
// Collect cash type inputs
val queryCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED, setOf(Cash.State::class.java))
val cashStates = serviceHub.vaultQueryService.queryBy<Cash.State>(queryCriteria).states
// extract our identity for convenience
val ourKeys = serviceHub.keyManagementService.keys
// Filter down to our own cash states with right currency and issuer
val suitableCashStates = cashStates.filter {
val state = it.state.data
// TODO: We may want to have the list of our states pre-cached somewhere for performance
(state.owner.owningKey in ourKeys) && (state.amount.token == amountRequired.token)
}
val ourParties = ourKeys.map { serviceHub.identityService.partyFromKey(it) ?: throw IllegalStateException("Unable to resolve party from key") }
val fungibleCriteria = QueryCriteria.FungibleAssetQueryCriteria(owner = ourParties)
val logicalExpression = builder { CashSchemaV1.PersistentCashState::currency.equal(amountRequired.token.product.currencyCode) }
val cashCriteria = QueryCriteria.VaultCustomQueryCriteria(logicalExpression)
// Collect cash type inputs
val suitableCashStates = serviceHub.vaultQueryService.queryBy<Cash.State>(fungibleCriteria.and(cashCriteria)).states
require(!suitableCashStates.isEmpty()) { "Insufficient funds" }
var remaining = amountRequired.quantity
// We will need all of the inputs to be on the same notary.
// For simplicity we just filter on the first notary encountered

View File

@ -12,7 +12,9 @@ import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
@ -21,15 +23,6 @@ import net.corda.core.utilities.seconds
import net.corda.core.utilities.unwrap
import java.security.PublicKey
// DOCSTART 1
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
inline fun <reified T : LinearState> ServiceHub.latest(ref: StateRef): StateAndRef<T> {
val linearHeads = vaultService.linearHeadsOfType<T>()
val original = toStateAndRef<T>(ref)
return linearHeads[original.state.data.linearId]!!
}
// DOCEND 1
// Minimal state model of a manual approval process
@CordaSerializable
enum class WorkflowState {
@ -150,8 +143,11 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
@Suspendable
override fun call(): StateAndRef<TradeApprovalContract.State> {
// Pull in the latest Vault version of the StateRef as a full StateAndRef
val latestRecord = serviceHub.latest<TradeApprovalContract.State>(ref)
// DOCSTART 1
val criteria = VaultQueryCriteria(stateRefs = listOf(ref))
val latestRecord = serviceHub.vaultQueryService.queryBy<TradeApprovalContract.State>(criteria).states.single()
// DOCEND 1
// Check the protocol hasn't already been run
require(latestRecord.ref == ref) {
"Input trade $ref is not latest version $latestRecord"

View File

@ -38,7 +38,6 @@ class FxTransactionBuildTutorialTest {
@After
fun cleanUp() {
println("Close DB")
mockNet.stopNodes()
}

View File

@ -26,10 +26,9 @@ class WorkflowTransactionBuildTutorialTest {
lateinit var nodeA: MockNetwork.MockNode
lateinit var nodeB: MockNetwork.MockNode
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
// Helper method to locate the latest Vault version of a LinearState
private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
val linearHeads = vaultQueryService.queryBy<T>(QueryCriteria.LinearStateQueryCriteria(linearId = listOf(ref))
.and(QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.UNCONSUMED)))
val linearHeads = vaultQueryService.queryBy<T>(QueryCriteria.LinearStateQueryCriteria(linearId = listOf(ref)))
return linearHeads.states.single()
}
@ -48,7 +47,6 @@ class WorkflowTransactionBuildTutorialTest {
@After
fun cleanUp() {
println("Close DB")
mockNet.stopNodes()
}

View File

@ -87,7 +87,7 @@ One of the first steps to forming a transaction is gathering the set of
input references. This process will clearly vary according to the nature
of the business process being captured by the smart contract and the
parameterised details of the request. However, it will generally involve
searching the Vault via the ``VaultService`` interface on the
searching the Vault via the ``VaultQueryService`` interface on the
``ServiceHub`` to locate the input states.
To give a few more specific details consider two simplified real world
@ -111,16 +111,16 @@ part of a simulated in-memory network of nodes.
to the VM options, and set Working directory to ``$PROJECT_DIR$``
so that the ``Quasar`` instrumentation is correctly configured.
For the Cash transaction lets assume the cash resources are using the
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
contract uses ``FungibleAsset`` states to model holdings of
interchangeable assets and allow the split/merge and summing of
states to meet a contractual obligation. We would normally use the
``generateSpend`` method on the ``VaultService`` to gather the required
amount of cash into a ``TransactionBuilder``, set the outputs and move
command. However, to elucidate more clearly example flow code is shown
here that will manually carry out the inputs queries using the lower
level ``VaultService``.
For the Cash transaction lets assume the cash resources are using the
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
contract uses ``FungibleAsset`` states to model holdings of
interchangeable assets and allow the split/merge and summing of
states to meet a contractual obligation. We would normally use the
``generateSpend`` method on the ``VaultService`` to gather the required
amount of cash into a ``TransactionBuilder``, set the outputs and move
command. However, to elucidate more clearly example flow code is shown
here that will manually carry out the inputs queries by specifying relevant
query criteria filters to the ``queryBy`` method of the ``VaultQueryService``.
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
:language: kotlin
@ -159,21 +159,14 @@ workflows will query the Vault for states of the right contract type and
in the right workflow state over the RPC interface. The RPC will then
initiate the relevant flow using ``StateRef``, or ``linearId`` values as
parameters to the flow to identify the states being operated upon. Thus
code to gather the latest input state would be:
code to gather the latest input state for a given ``StateRef`` would use
the ``VaultQueryService`` as follows:
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
.. container:: codeset
.. sourcecode:: kotlin
// Pull in the latest Vault version of the StateRef as a full StateAndRef
val latestRecord = serviceHub.latest<TradeApprovalContract.State>(ref)
Generating Commands
-------------------

View File

@ -15,9 +15,7 @@ import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.TokenizableAssetInfo
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.ServiceType
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.node.services.*
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.TransactionBuilder
import java.math.BigDecimal

View File

@ -7,8 +7,12 @@ import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.issuedBy
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.Party
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.DEFAULT_PAGE_NUM
import net.corda.core.node.services.vault.PageSpecification
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import java.util.*
@ -47,13 +51,9 @@ class CashExitFlow(val amount: Amount<Currency>, val issueRef: OpaqueBytes, prog
throw CashException("Exiting more cash than exists", e)
}
// Work out who the owners of the burnt states were
val inputStatesNullable = serviceHub.vaultService.statesForRefs(builder.inputStates())
val inputStates = inputStatesNullable.values.filterNotNull().map { it.data }
if (inputStatesNullable.size != inputStates.size) {
val unresolvedStateRefs = inputStatesNullable.filter { it.value == null }.map { it.key }
throw IllegalStateException("Failed to resolve input StateRefs: $unresolvedStateRefs")
}
// Work out who the owners of the burnt states were (specify page size so we don't silently drop any if > DEFAULT_PAGE_SIZE)
val inputStates = serviceHub.vaultQueryService.queryBy<Cash.State>(VaultQueryCriteria(stateRefs = builder.inputStates()),
PageSpecification(pageNumber = DEFAULT_PAGE_NUM, pageSize = builder.inputStates().size)).states
// TODO: Is it safe to drop participants we don't know how to contact? Does not knowing how to contact them
// count as a reason to fail?

View File

@ -6,12 +6,16 @@ import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.unconsumedStates
import net.corda.core.node.services.queryBy
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.OpaqueBytes
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.services.vault.HibernateVaultQueryImpl
import net.corda.node.services.vault.NodeVaultService
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase
@ -54,6 +58,7 @@ class CashTests : TestDependencyInjectionBase() {
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val hibernateConfig = HibernateConfiguration(NodeSchemaService(), makeTestDatabaseProperties())
miniCorpServices = object : MockServices(MINI_CORP_KEY) {
override val keyManagementService: MockKeyManagementService = MockKeyManagementService(identityService, MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY)
override val vaultService: VaultService = makeVaultService(dataSourceProps)
@ -65,6 +70,7 @@ class CashTests : TestDependencyInjectionBase() {
// Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions.
vaultService.notifyAll(txs.map { it.tx })
}
override val vaultQueryService : VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService.updatesPublisher)
}
miniCorpServices.fillWithSomeTestCash(howMuch = 100.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
@ -76,7 +82,7 @@ class CashTests : TestDependencyInjectionBase() {
miniCorpServices.fillWithSomeTestCash(howMuch = 80.SWISS_FRANCS, atLeastThisManyStates = 1, atMostThisManyStates = 1,
issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_IDENTITY_1)
vaultStatesUnconsumed = miniCorpServices.vaultService.unconsumedStates<Cash.State>().toList()
vaultStatesUnconsumed = miniCorpServices.vaultQueryService.queryBy<Cash.State>().states
}
resetTestSerialization()
}

View File

@ -176,21 +176,21 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
@Suppress("UNCHECKED_CAST")
column as Path<Long?>?
val aggregateExpression =
when (columnPredicate.type) {
AggregateFunctionType.SUM -> criteriaBuilder.sum(column)
AggregateFunctionType.AVG -> criteriaBuilder.avg(column)
AggregateFunctionType.COUNT -> criteriaBuilder.count(column)
AggregateFunctionType.MAX -> criteriaBuilder.max(column)
AggregateFunctionType.MIN -> criteriaBuilder.min(column)
}
when (columnPredicate.type) {
AggregateFunctionType.SUM -> criteriaBuilder.sum(column)
AggregateFunctionType.AVG -> criteriaBuilder.avg(column)
AggregateFunctionType.COUNT -> criteriaBuilder.count(column)
AggregateFunctionType.MAX -> criteriaBuilder.max(column)
AggregateFunctionType.MIN -> criteriaBuilder.min(column)
}
aggregateExpressions.add(aggregateExpression)
// optionally order by this aggregate function
expression.orderBy?.let {
val orderCriteria =
when (expression.orderBy!!) {
Sort.Direction.ASC -> criteriaBuilder.asc(aggregateExpression)
Sort.Direction.DESC -> criteriaBuilder.desc(aggregateExpression)
}
when (expression.orderBy!!) {
Sort.Direction.ASC -> criteriaBuilder.asc(aggregateExpression)
Sort.Direction.DESC -> criteriaBuilder.desc(aggregateExpression)
}
criteriaQuery.orderBy(orderCriteria)
}
// add optional group by clauses
@ -374,10 +374,10 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
}
val selections =
if (aggregateExpressions.isEmpty())
listOf(vaultStates).plus(rootEntities.map { it.value })
else
aggregateExpressions
if (aggregateExpressions.isEmpty())
listOf(vaultStates).plus(rootEntities.map { it.value })
else
aggregateExpressions
criteriaQuery.multiselect(selections)
val combinedPredicates = joinPredicates.plus(predicateSet)
criteriaQuery.where(*combinedPredicates.toTypedArray())
@ -439,21 +439,21 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
private fun parse(sortAttribute: Sort.Attribute): Triple<Class<out PersistentState>, String, String?> {
val entityClassAndColumnName : Triple<Class<out PersistentState>, String, String?> =
when(sortAttribute) {
is Sort.CommonStateAttribute -> {
Triple(VaultSchemaV1.VaultStates::class.java, sortAttribute.attributeParent, sortAttribute.attributeChild)
when(sortAttribute) {
is Sort.CommonStateAttribute -> {
Triple(VaultSchemaV1.VaultStates::class.java, sortAttribute.attributeParent, sortAttribute.attributeChild)
}
is Sort.VaultStateAttribute -> {
Triple(VaultSchemaV1.VaultStates::class.java, sortAttribute.attributeName, null)
}
is Sort.LinearStateAttribute -> {
Triple(VaultSchemaV1.VaultLinearStates::class.java, sortAttribute.attributeName, null)
}
is Sort.FungibleStateAttribute -> {
Triple(VaultSchemaV1.VaultFungibleStates::class.java, sortAttribute.attributeName, null)
}
else -> throw VaultQueryException("Invalid sort attribute: $sortAttribute")
}
is Sort.VaultStateAttribute -> {
Triple(VaultSchemaV1.VaultStates::class.java, sortAttribute.attributeName, null)
}
is Sort.LinearStateAttribute -> {
Triple(VaultSchemaV1.VaultLinearStates::class.java, sortAttribute.attributeName, null)
}
is Sort.FungibleStateAttribute -> {
Triple(VaultSchemaV1.VaultFungibleStates::class.java, sortAttribute.attributeName, null)
}
else -> throw VaultQueryException("Invalid sort attribute: $sortAttribute")
}
return entityClassAndColumnName
}
}

View File

@ -102,6 +102,7 @@ class HibernateVaultQueryImpl(hibernateConfig: HibernateConfiguration,
statesAndRefs.add(StateAndRef(state, stateRef))
}
else {
// TODO: improve typing of returned other results
log.debug { "OtherResults: ${Arrays.toString(result.toArray())}" }
otherResults.addAll(result.toArray().asList())
}

View File

@ -11,9 +11,9 @@ import net.corda.core.getOrThrow
import net.corda.core.messaging.*
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.Vault
import net.corda.core.node.services.unconsumedStates
import net.corda.core.transactions.SignedTransaction
import net.corda.core.node.services.queryBy
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow
import net.corda.node.internal.CordaRPCOpsImpl
@ -88,7 +88,7 @@ class CordaRPCOpsImplTest {
// Check the monitoring service wallet is empty
aliceNode.database.transaction {
assertFalse(aliceNode.services.vaultService.unconsumedStates<ContractState>().iterator().hasNext())
assertFalse(aliceNode.services.vaultQueryService.queryBy<ContractState>().totalStatesAvailable > 0)
}
// Tell the monitoring service node to issue some cash

View File

@ -7,12 +7,18 @@ import net.corda.core.flows.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.DEFAULT_PAGE_NUM
import net.corda.core.node.services.vault.PageSpecification
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.node.services.vault.Sort
import net.corda.core.node.services.vault.SortAttribute
import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.DUMMY_NOTARY
import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.statemachine.StateMachineManager
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockNetwork
import org.junit.After
@ -114,10 +120,10 @@ class ScheduledFlowTests {
nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.legalIdentity))
mockNet.waitQuiescent()
val stateFromA = nodeA.database.transaction {
nodeA.services.vaultService.linearHeadsOfType<ScheduledState>().values.first()
nodeA.services.vaultQueryService.queryBy<ScheduledState>().states.single()
}
val stateFromB = nodeB.database.transaction {
nodeB.services.vaultService.linearHeadsOfType<ScheduledState>().values.first()
nodeB.services.vaultQueryService.queryBy<ScheduledState>().states.single()
}
assertEquals(1, countScheduledFlows)
assertEquals(stateFromA, stateFromB, "Must be same copy on both nodes")
@ -132,14 +138,31 @@ class ScheduledFlowTests {
nodeB.services.startFlow(InsertInitialStateFlow(nodeA.info.legalIdentity))
}
mockNet.waitQuiescent()
val statesFromA = nodeA.database.transaction {
nodeA.services.vaultService.linearHeadsOfType<ScheduledState>()
queryStatesWithPaging(nodeA.services.vaultQueryService)
}
val statesFromB = nodeB.database.transaction {
nodeB.services.vaultService.linearHeadsOfType<ScheduledState>()
queryStatesWithPaging(nodeB.services.vaultQueryService)
}
assertEquals(2 * N, statesFromA.count(), "Expect all states to be present")
assertEquals(statesFromA, statesFromB, "Expect identical data on both nodes")
assertTrue("Expect all states have run the scheduled task", statesFromB.values.all { it.state.data.processed })
assertTrue("Expect all states have run the scheduled task", statesFromB.all { it.state.data.processed })
}
// Demonstrate Vault Query paging and sorting
val PAGE_SIZE = 20
val sorting = Sort(listOf(Sort.SortColumn(SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID), Sort.Direction.DESC)))
private fun queryStatesWithPaging(vaultQueryService: VaultQueryService): List<StateAndRef<ScheduledState>> {
var pageNumber = DEFAULT_PAGE_NUM
val states = mutableListOf<StateAndRef<ScheduledState>>()
do {
val pageSpec = PageSpecification(pageSize = PAGE_SIZE, pageNumber = pageNumber)
val results = vaultQueryService.queryBy<ScheduledState>(VaultQueryCriteria(), pageSpec, sorting)
states.addAll(results.states)
pageNumber++
} while ((pageSpec.pageSize * (pageNumber)) <= results.totalStatesAvailable)
return states.toList()
}
}

View File

@ -10,7 +10,7 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party
import net.corda.core.node.services.unconsumedStates
import net.corda.core.node.services.queryBy
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.services.NotifyTransactionHandler
@ -56,12 +56,12 @@ class DataVendingServiceTests {
// Complete the cash transaction, and then manually relay it
val tx = registerNode.services.signInitialTransaction(ptx)
vaultServiceNode.database.transaction {
assertThat(vaultServiceNode.services.vaultService.unconsumedStates<Cash.State>()).isEmpty()
assertThat(vaultServiceNode.services.vaultQueryService.queryBy<Cash.State>().states.isEmpty())
registerNode.sendNotifyTx(tx, vaultServiceNode)
// Check the transaction is in the receiving node
val actual = vaultServiceNode.services.vaultService.unconsumedStates<Cash.State>().singleOrNull()
val actual = vaultServiceNode.services.vaultQueryService.queryBy<Cash.State>().states.singleOrNull()
val expected = tx.tx.outRef<Cash.State>(0)
assertEquals(expected, actual)
}
@ -86,12 +86,12 @@ class DataVendingServiceTests {
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid
val tx = registerNode.services.signInitialTransaction(ptx)
vaultServiceNode.database.transaction {
assertThat(vaultServiceNode.services.vaultService.unconsumedStates<Cash.State>()).isEmpty()
assertThat(vaultServiceNode.services.vaultQueryService.queryBy<Cash.State>().states.isEmpty())
registerNode.sendNotifyTx(tx, vaultServiceNode)
// Check the transaction is not in the receiving node
assertThat(vaultServiceNode.services.vaultService.unconsumedStates<Cash.State>()).isEmpty()
assertThat(vaultServiceNode.services.vaultQueryService.queryBy<Cash.State>().states.isEmpty())
}
}

View File

@ -3,11 +3,9 @@ package net.corda.node.services.statemachine
import co.paralleluniverse.fibers.Fiber
import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.ListenableFuture
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.DOLLARS
import net.corda.core.contracts.StateAndRef
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.generateKeyPair
import net.corda.core.crypto.random63BitValue
import net.corda.core.flatMap
@ -19,7 +17,6 @@ import net.corda.core.messaging.MessageRecipients
import net.corda.core.node.services.PartyInfo
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.unconsumedStates
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.toFuture
@ -597,13 +594,6 @@ class FlowFrameworkTests {
}
}
@Test
fun `lazy db iterator left on stack during checkpointing`() {
val result = node2.services.startFlow(VaultAccessFlow()).resultFuture
mockNet.runNetwork()
assertThatThrownBy { result.getOrThrow() }.hasMessageContaining("Vault").hasMessageContaining("private method")
}
@Test
fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
@ -917,14 +907,6 @@ class FlowFrameworkTests {
}
}
private class VaultAccessFlow : FlowLogic<Unit>() {
@Suspendable
override fun call() {
serviceHub.vaultService.unconsumedStates<Cash.State>().filter { true }
waitForLedgerCommit(SecureHash.zeroHash)
}
}
@InitiatingFlow
private class VaultQueryFlow(val stx: SignedTransaction, val otherParty: Party) : FlowLogic<List<StateAndRef<ContractState>>>() {
@Suspendable

View File

@ -7,7 +7,12 @@ import net.corda.core.contracts.*
import net.corda.core.crypto.generateKeyPair
import net.corda.core.crypto.sign
import net.corda.core.identity.AnonymousParty
import net.corda.core.node.services.*
import net.corda.core.node.services.StatesNotAvailableException
import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.transactions.NotaryChangeWireTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
@ -18,13 +23,11 @@ import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase
import net.corda.schemas.CommercialPaperSchemaV1
import net.corda.testing.*
import net.corda.testing.contracts.fillWithSomeTestCash
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.After
@ -41,6 +44,7 @@ import kotlin.test.assertTrue
class NodeVaultServiceTest : TestDependencyInjectionBase() {
lateinit var services: MockServices
val vaultSvc: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence
@Before
@ -49,8 +53,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val customSchemas = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1)
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
val hibernateConfig = HibernateConfiguration(NodeSchemaService(), makeTestDatabaseProperties())
services = object : MockServices() {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)
@ -61,8 +64,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
// Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions.
vaultService.notifyAll(txs.map { it.tx })
}
override val vaultQueryService: VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService.updatesPublisher)
override val vaultQueryService : VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService.updatesPublisher)
}
}
}
@ -79,10 +81,11 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L))
val w1 = vaultSvc.unconsumedStates<Cash.State>()
val w1 = vaultQuery.queryBy<Cash.State>().states
assertThat(w1).hasSize(3)
val originalVault = vaultSvc
val originalVaultQuery = vaultQuery
val services2 = object : MockServices() {
override val vaultService: VaultService get() = originalVault
override fun recordTransactions(txs: Iterable<SignedTransaction>) {
@ -91,9 +94,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
vaultService.notify(stx.tx)
}
}
override val vaultQueryService : VaultQueryService get() = originalVaultQuery
}
val w2 = services2.vaultService.unconsumedStates<Cash.State>()
val w2 = services2.vaultQueryService.queryBy<Cash.State>().states
assertThat(w2).hasSize(3)
}
}
@ -104,11 +108,10 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L))
val w1 = vaultSvc.unconsumedStates<Cash.State>().toList()
val w1 = vaultQuery.queryBy<Cash.State>().states
assertThat(w1).hasSize(3)
val stateRefs = listOf(w1[1].ref, w1[2].ref)
val states = vaultSvc.statesForRefs(stateRefs)
val states = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(stateRefs = listOf(w1[1].ref, w1[2].ref))).states
assertThat(states).hasSize(2)
}
}
@ -119,7 +122,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L))
val unconsumedStates = vaultSvc.unconsumedStates<Cash.State>().toList()
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(3)
val stateRefsToSoftLock = NonEmptySet.of(unconsumedStates[1].ref, unconsumedStates[2].ref)
@ -134,17 +137,17 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
assertThat(vaultSvc.softLockedStates<Cash.State>(softLockId)).hasSize(2)
// excluding softlocked states
val unlockedStates1 = vaultSvc.unconsumedStates<Cash.State>(includeSoftLockedStates = false).toList()
val unlockedStates1 = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(includeSoftlockedStates = false)).states
assertThat(unlockedStates1).hasSize(1)
// soft lock release one of the states explicitly
vaultSvc.softLockRelease(softLockId, NonEmptySet.of(unconsumedStates[1].ref))
val unlockedStates2 = vaultSvc.unconsumedStates<Cash.State>(includeSoftLockedStates = false).toList()
val unlockedStates2 = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(includeSoftlockedStates = false)).states
assertThat(unlockedStates2).hasSize(2)
// soft lock release the rest by id
vaultSvc.softLockRelease(softLockId)
val unlockedStates = vaultSvc.unconsumedStates<Cash.State>(includeSoftLockedStates = false).toList()
val unlockedStates = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(includeSoftlockedStates = false)).states
assertThat(unlockedStates).hasSize(3)
// should be back to original states
@ -297,7 +300,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L))
val unconsumedStates = vaultSvc.unconsumedStates<Cash.State>().toList()
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(1)
val spendableStatesUSD = (vaultSvc as NodeVaultService).unconsumedStatesForSpending<Cash.State>(100.DOLLARS, lockId = UUID.randomUUID())
@ -333,7 +336,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), issuerKey = BOC_KEY, ref = OpaqueBytes.of(2))
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(3)), issuerKey = BOC_KEY, ref = OpaqueBytes.of(3))
val unconsumedStates = vaultSvc.unconsumedStates<Cash.State>().toList()
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(4)
val spendableStatesUSD = vaultSvc.unconsumedStatesForSpending<Cash.State>(200.DOLLARS, lockId = UUID.randomUUID(),
@ -351,7 +354,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 1, 1, Random(0L))
val unconsumedStates = vaultSvc.unconsumedStates<Cash.State>().toList()
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(1)
val spendableStatesUSD = (vaultSvc as NodeVaultService).unconsumedStatesForSpending<Cash.State>(110.DOLLARS, lockId = UUID.randomUUID())
@ -367,7 +370,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 2, 2, Random(0L))
val unconsumedStates = vaultSvc.unconsumedStates<Cash.State>().toList()
val unconsumedStates = vaultQuery.queryBy<Cash.State>().states
assertThat(unconsumedStates).hasSize(2)
val spendableStatesUSD = (vaultSvc as NodeVaultService).unconsumedStatesForSpending<Cash.State>(1.DOLLARS, lockId = UUID.randomUUID())
@ -386,7 +389,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 10, 10, Random(0L))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 10, 10, Random(0L))
val allStates = vaultSvc.unconsumedStates<Cash.State>()
val allStates = vaultQuery.queryBy<Cash.State>().states
assertThat(allStates).hasSize(30)
for (i in 1..5) {

View File

@ -1,8 +1,6 @@
package net.corda.node.services.vault
import net.corda.contracts.CommercialPaper
import net.corda.contracts.Commodity
import net.corda.contracts.DealState
import net.corda.contracts.*
import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.core.contracts.*
@ -1254,7 +1252,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
}
@Test
fun `unconsumed deal states paged and sorted`() {
fun `unconsumed deal states sorted`() {
database.transaction {
val linearStates = services.fillWithSomeTestLinearStates(10)
@ -1385,6 +1383,28 @@ class VaultQueryTests : TestDependencyInjectionBase() {
}
}
@Test
fun `DEPRECATED DealState dealsWith helper method`() {
database.transaction {
// specify a different participant to the node owner (MEGA_CORP)
val parties = listOf(MINI_CORP)
services.fillWithSomeTestLinearStates(2, "TEST")
services.fillWithSomeTestDeals(listOf("456"), parties)
services.fillWithSomeTestDeals(listOf("123", "789"))
// DOCSTART VaultQueryExample11
val criteria = LinearStateQueryCriteria(participants = parties)
val results = vaultQuerySvc.queryBy<DealState>(criteria)
// DOCEND
assertThat(results.states).hasSize(1)
val states = vaultSvc.dealsWith<DummyDealContract.State>(MINI_CORP)
assertThat(states).hasSize(1)
}
}
/**
* Deal Contract state to be removed as is duplicate of LinearState
*/
@ -1834,7 +1854,8 @@ class VaultQueryTests : TestDependencyInjectionBase() {
database.transaction {
services.fillWithSomeTestLinearStates(1, "TEST1")
services.fillWithSomeTestLinearStates(1, "TEST2")
val aState = services.fillWithSomeTestLinearStates(1, "TEST2").states
services.consumeLinearStates(aState.toList())
val uuid = services.fillWithSomeTestLinearStates(1, "TEST3").states.first().state.data.linearId.id
// 2 unconsumed states with same external ID, 1 with different external ID

View File

@ -5,23 +5,22 @@ import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.contracts.getCashBalance
import net.corda.core.contracts.*
import net.corda.core.identity.AnonymousParty
import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultQueryService
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.consumedStates
import net.corda.core.node.services.unconsumedStates
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase
import net.corda.schemas.CommercialPaperSchemaV1
import net.corda.testing.*
import net.corda.testing.contracts.*
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
@ -37,6 +36,7 @@ import kotlin.test.assertEquals
class VaultWithCashTest : TestDependencyInjectionBase() {
lateinit var services: MockServices
val vault: VaultService get() = services.vaultService
val vaultQuery: VaultQueryService get() = services.vaultQueryService
lateinit var database: CordaPersistence
val notaryServices = MockServices(DUMMY_NOTARY_KEY)
@ -46,8 +46,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val dataSourceProps = makeTestDataSourceProperties()
database = configureDatabase(dataSourceProps, makeTestDatabaseProperties())
database.transaction {
val customSchemas = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1)
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), makeTestDatabaseProperties())
val hibernateConfig = HibernateConfiguration(NodeSchemaService(), makeTestDatabaseProperties())
services = object : MockServices() {
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)
@ -58,8 +57,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
// Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions.
vaultService.notifyAll(txs.map { it.tx })
}
override val vaultQueryService: VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService.updatesPublisher)
override val vaultQueryService : VaultQueryService = HibernateVaultQueryImpl(hibernateConfig, vaultService.updatesPublisher)
}
}
}
@ -76,7 +74,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
// Fix the PRNG so that we get the same splits every time.
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L))
val w = vault.unconsumedStates<Cash.State>().toList()
val w = vaultQuery.queryBy<Cash.State>().states
assertEquals(3, w.size)
val state = w[0].state.data
@ -139,7 +137,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
ownedBy = AnonymousParty(freshKey))
println("Cash balance: ${services.getCashBalance(USD)}")
assertThat(vault.unconsumedStates<Cash.State>()).hasSize(10)
assertThat(vaultQuery.queryBy<Cash.State>().states).hasSize(10)
assertThat(vault.softLockedStates<Cash.State>()).hasSize(0)
}
@ -154,16 +152,20 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey)
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultQuery.queryBy<Cash.State>()
val consumedStates1 = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
println("""txn1 states:
UNCONSUMED: ${vault.unconsumedStates<Cash.State>().count()} : ${vault.unconsumedStates<Cash.State>()},
CONSUMED: ${vault.consumedStates<Cash.State>().count()} : ${vault.consumedStates<Cash.State>()},
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
LOCKED: ${vault.softLockedStates<Cash.State>().count()} : ${vault.softLockedStates<Cash.State>()}
""")
services.recordTransactions(txn1)
println("txn1: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultQuery.queryBy<Cash.State>()
val consumedStates2 = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
println("""txn1 states:
UNCONSUMED: ${vault.unconsumedStates<Cash.State>().count()} : ${vault.unconsumedStates<Cash.State>()},
CONSUMED: ${vault.consumedStates<Cash.State>().count()} : ${vault.consumedStates<Cash.State>()},
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
LOCKED: ${vault.softLockedStates<Cash.State>().count()} : ${vault.softLockedStates<Cash.State>()}
""")
txn1
@ -184,16 +186,20 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey)
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultQuery.queryBy<Cash.State>()
val consumedStates1 = vaultQuery.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
println("""txn2 states:
UNCONSUMED: ${vault.unconsumedStates<Cash.State>().count()} : ${vault.unconsumedStates<Cash.State>()},
CONSUMED: ${vault.consumedStates<Cash.State>().count()} : ${vault.consumedStates<Cash.State>()},
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
LOCKED: ${vault.softLockedStates<Cash.State>().count()} : ${vault.softLockedStates<Cash.State>()}
""")
services.recordTransactions(txn2)
println("txn2: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultQuery.queryBy<Cash.State>()
val consumedStates2 = vaultQuery.queryBy<Cash.State>()
println("""txn2 states:
UNCONSUMED: ${vault.unconsumedStates<Cash.State>().count()} : ${vault.unconsumedStates<Cash.State>()},
CONSUMED: ${vault.consumedStates<Cash.State>().count()} : ${vault.consumedStates<Cash.State>()},
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
LOCKED: ${vault.softLockedStates<Cash.State>().count()} : ${vault.softLockedStates<Cash.State>()}
""")
txn2
@ -250,7 +256,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
dummyIssue.toLedgerTransaction(services).verify()
services.recordTransactions(dummyIssue)
assertThat(vault.unconsumedStates<DummyLinearContract.State>()).hasSize(1)
assertThat(vaultQuery.queryBy<DummyLinearContract.State>().states).hasSize(1)
// Move the same state
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
@ -263,7 +269,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
dummyIssue.toLedgerTransaction(services).verify()
services.recordTransactions(dummyMove)
assertThat(vault.unconsumedStates<DummyLinearContract.State>()).hasSize(1)
assertThat(vaultQuery.queryBy<DummyLinearContract.State>().states).hasSize(1)
}
}
@ -275,11 +281,11 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshKey))
services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 2, 2, Random(0L))
services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 1, 1, Random(0L))
val cash = vault.unconsumedStates<Cash.State>()
val cash = vaultQuery.queryBy<Cash.State>().states
cash.forEach { println(it.state.data.amount) }
services.fillWithSomeTestDeals(listOf("123", "456", "789"))
val deals = vault.unconsumedStates<DummyDealContract.State>()
val deals = vaultQuery.queryBy<DummyDealContract.State>().states
deals.forEach { println(it.state.data.ref) }
}
@ -291,10 +297,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val spendTX = services.addSignature(spendPTX, freshKey)
services.recordTransactions(spendTX)
val consumedStates = vault.consumedStates<ContractState>()
val consumedStates = vaultQuery.queryBy<ContractState>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED)).states
assertEquals(3, consumedStates.count())
val unconsumedStates = vault.unconsumedStates<ContractState>()
val unconsumedStates = vaultQuery.queryBy<ContractState>().states
assertEquals(7, unconsumedStates.count())
}
}
@ -307,11 +313,11 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction {
services.fillWithSomeTestDeals(listOf("123", "456", "789"))
val deals = vault.unconsumedStates<DummyDealContract.State>().toList()
val deals = vaultQuery.queryBy<DummyDealContract.State>().states
deals.forEach { println(it.state.data.ref) }
services.fillWithSomeTestLinearStates(3)
val linearStates = vault.unconsumedStates<DummyLinearContract.State>().toList()
val linearStates = vaultQuery.queryBy<DummyLinearContract.State>().states
linearStates.forEach { println(it.state.data.linearId) }
// Create a txn consuming different contract types
@ -327,10 +333,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
dummyMove.toLedgerTransaction(services).verify()
services.recordTransactions(dummyMove)
val consumedStates = vault.consumedStates<ContractState>()
val consumedStates = vaultQuery.queryBy<ContractState>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED)).states
assertEquals(2, consumedStates.count())
val unconsumedStates = vault.unconsumedStates<ContractState>()
val unconsumedStates = vaultQuery.queryBy<ContractState>().states
assertEquals(6, unconsumedStates.count())
}
}

View File

@ -5,6 +5,7 @@ import net.corda.contracts.asset.Cash
import net.corda.core.contracts.DOLLARS
import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultTrackBy
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.Vault
import net.corda.core.node.services.vault.QueryCriteria
@ -37,10 +38,10 @@ class BankOfCordaRPCClientTest {
// Register for Bank of Corda Vault updates
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
val (_, vaultUpdatesBoc) = bocProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
val vaultUpdatesBoc = bocProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria).updates
// Register for Big Corporation Vault updates
val (_, vaultUpdatesBigCorp) = bigCorpProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
val vaultUpdatesBigCorp = bigCorpProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria).updates
// Kick-off actual Issuer Flow
val anonymous = true

View File

@ -3,6 +3,7 @@ package net.corda.irs
import com.google.common.util.concurrent.Futures
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.getOrThrow
import net.corda.core.messaging.vaultTrackBy
import net.corda.core.node.services.ServiceInfo
import net.corda.core.toFuture
import net.corda.core.utilities.NetworkHostAndPort
@ -81,7 +82,7 @@ class IRSDemoTest : IntegrationTestCategory {
fun getFixingDateObservable(config: FullNodeConfiguration): Observable<LocalDate?> {
val client = CordaRPCClient(config.rpcAddress!!, initialiseSerialization = false)
val proxy = client.start("user", "password").proxy
val vaultUpdates = proxy.vaultAndUpdates().updates
val vaultUpdates = proxy.vaultTrackBy<InterestRateSwap.State>().updates
return vaultUpdates.map { update ->
val irsStates = update.produced.map { it.state.data }.filterIsInstance<InterestRateSwap.State>()

View File

@ -5,6 +5,8 @@ import net.corda.core.contracts.filterStatesOfType
import net.corda.core.getOrThrow
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.utilities.loggerFor
import net.corda.irs.contract.InterestRateSwap
import net.corda.irs.flows.AutoOfferFlow
@ -36,8 +38,7 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) {
private fun generateDealLink(deal: InterestRateSwap.State) = "/api/irs/deals/" + deal.common.tradeID
private fun getDealByRef(ref: String): InterestRateSwap.State? {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
val vault = rpc.vaultQueryBy<InterestRateSwap.State>().states
val states = vault.filterStatesOfType<InterestRateSwap.State>().filter { it.state.data.ref == ref }
return if (states.isEmpty()) null else {
val deals = states.map { it.state.data }
@ -46,8 +47,7 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) {
}
private fun getAllDeals(): Array<InterestRateSwap.State> {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
val vault = rpc.vaultQueryBy<InterestRateSwap.State>().states
val states = vault.filterStatesOfType<InterestRateSwap.State>()
val swaps = states.map { it.state.data }.toTypedArray()
return swaps

View File

@ -4,17 +4,18 @@ import co.paralleluniverse.fibers.Suspendable
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.google.common.util.concurrent.*
import net.corda.core.*
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.flatMap
import net.corda.core.flows.FlowLogic
import net.corda.core.internal.FlowStateMachine
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.internal.FlowStateMachine
import net.corda.core.map
import net.corda.core.node.services.queryBy
import net.corda.core.thenMatch
import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction
import net.corda.testing.DUMMY_CA
import net.corda.flows.TwoPartyDealFlow.Acceptor
import net.corda.flows.TwoPartyDealFlow.AutoOffer
import net.corda.flows.TwoPartyDealFlow.Instigator
@ -22,6 +23,7 @@ import net.corda.irs.contract.InterestRateSwap
import net.corda.irs.flows.FixingFlow
import net.corda.jackson.JacksonSupport
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.testing.DUMMY_CA
import net.corda.testing.node.InMemoryMessagingNetwork
import rx.Observable
import java.security.PublicKey
@ -76,19 +78,16 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
return future
}
private fun loadLinearHeads(node: SimulatedNode): Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> {
return node.database.transaction {
node.services.vaultService.linearHeadsOfType<InterestRateSwap.State>()
}
}
private fun doNextFixing(i: Int, j: Int): ListenableFuture<Unit>? {
println("Doing a fixing between $i and $j")
val node1: SimulatedNode = banks[i]
val node2: SimulatedNode = banks[j]
val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> = loadLinearHeads(node1)
val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.values.single()
val swaps =
node1.database.transaction {
node1.services.vaultQueryService.queryBy<InterestRateSwap.State>().states
}
val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.single()
// Do we have any more days left in this deal's lifetime? If not, return.
val nextFixingDate = theDealRef.state.data.calculation.nextFixingDate() ?: return null

View File

@ -4,7 +4,6 @@ import com.opengamma.strata.basics.currency.MultiCurrencyAmount
import net.corda.client.rpc.notUsed
import net.corda.contracts.DealState
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.filterStatesOfType
import net.corda.core.crypto.parsePublicKeyBase58
import net.corda.core.crypto.toBase58String
import net.corda.core.getOrThrow
@ -12,6 +11,7 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.services.ServiceType
import net.corda.vega.analytics.InitialMarginTriple
import net.corda.vega.contracts.IRSState
@ -38,9 +38,10 @@ class PortfolioApi(val rpc: CordaRPCOps) {
private val portfolioUtils = PortfolioApiUtils(ownParty)
private inline fun <reified T : DealState> dealsWith(party: AbstractParty): List<StateAndRef<T>> {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
return vault.filterStatesOfType<T>().filter { it.state.data.participants.any { it == party } }
val linearStates = rpc.vaultQueryBy<T>().states
// TODO: enhancement to Vault Query to check for any participant in participants attribute
// QueryCriteria.LinearStateQueryCriteria(participants = anyOf(party))
return linearStates.filter { it.state.data.participants.any { it == party } }
}
/**

View File

@ -16,6 +16,8 @@ import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.Party
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.unwrap
@ -26,7 +28,6 @@ import net.corda.vega.analytics.*
import net.corda.vega.contracts.*
import net.corda.vega.portfolio.Portfolio
import net.corda.vega.portfolio.toPortfolio
import net.corda.vega.portfolio.toStateAndRef
import java.time.LocalDate
/**
@ -68,6 +69,7 @@ object SimmFlow {
myIdentity = serviceHub.myInfo.legalIdentity
val trades = serviceHub.vaultService.dealsWith<IRSState>(otherParty)
val portfolio = Portfolio(trades, valuationDate)
if (existing == null) {
agreePortfolio(portfolio)
@ -75,6 +77,7 @@ object SimmFlow {
updatePortfolio(portfolio, existing)
}
val portfolioStateRef = serviceHub.vaultService.dealsWith<PortfolioState>(otherParty).first()
val state = updateValuation(portfolioStateRef)
logger.info("SimmFlow done")
return state
@ -104,7 +107,8 @@ object SimmFlow {
private fun updateValuation(stateRef: StateAndRef<PortfolioState>): RevisionedState<PortfolioState.Update> {
logger.info("Agreeing valuations")
val state = stateRef.state.data
val portfolio = state.portfolio.toStateAndRef<IRSState>(serviceHub).toPortfolio()
val portfolio = serviceHub.vaultQueryService.queryBy<IRSState>(VaultQueryCriteria(stateRefs = state.portfolio)).states.toPortfolio()
val valuer = serviceHub.identityService.partyFromAnonymous(state.valuer)
require(valuer != null) { "Valuer party must be known to this node" }
val valuation = agreeValuation(portfolio, valuationDate, valuer!!)
@ -308,7 +312,7 @@ object SimmFlow {
@Suspendable
private fun updateValuation(stateRef: StateAndRef<PortfolioState>) {
val portfolio = stateRef.state.data.portfolio.toStateAndRef<IRSState>(serviceHub).toPortfolio()
val portfolio = serviceHub.vaultQueryService.queryBy<IRSState>(VaultQueryCriteria(stateRefs = stateRef.state.data.portfolio)).states.toPortfolio()
val valuer = serviceHub.identityService.partyFromAnonymous(stateRef.state.data.valuer) ?: throw IllegalStateException("Unknown valuer party ${stateRef.state.data.valuer}")
val valuation = agreeValuation(portfolio, offer.valuationDate, valuer)
subFlow(object : StateRevisionFlow.Receiver<PortfolioState.Update>(replyToParty) {

View File

@ -5,7 +5,8 @@ import net.corda.core.contracts.StateRef
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.SchedulableFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.vega.contracts.PortfolioState
import java.time.LocalDate
@ -19,7 +20,7 @@ object SimmRevaluation {
class Initiator(val curStateRef: StateRef, val valuationDate: LocalDate) : FlowLogic<Unit>() {
@Suspendable
override fun call(): Unit {
val stateAndRef = serviceHub.vaultService.linearHeadsOfType<PortfolioState>().values.first { it.ref == curStateRef }
val stateAndRef = serviceHub.vaultQueryService.queryBy<PortfolioState>(VaultQueryCriteria(stateRefs = listOf(curStateRef))).states.single()
val curState = stateAndRef.state.data
val myIdentity = serviceHub.myInfo.legalIdentity
if (myIdentity == curState.participants[0]) {

View File

@ -1,11 +1,11 @@
package net.corda.vega.portfolio
import net.corda.client.rpc.notUsed
import net.corda.core.contracts.*
import net.corda.core.identity.Party
import net.corda.core.internal.sum
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.ServiceHub
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.vega.contracts.IRSState
import net.corda.vega.contracts.SwapData
import java.math.BigDecimal
@ -35,16 +35,5 @@ fun List<StateAndRef<IRSState>>.toPortfolio(): Portfolio {
}
inline fun <reified T : ContractState> List<StateRef>.toStateAndRef(rpc: CordaRPCOps): List<StateAndRef<T>> {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
val stateRefs = vault.associateBy { it.ref }
return mapNotNull { stateRefs[it] }.filterStatesOfType<T>()
}
// TODO: This should probably have its generics fixed and moved into the core platform API.
@Suppress("UNCHECKED_CAST")
fun <T : ContractState> List<StateRef>.toStateAndRef(services: ServiceHub): List<StateAndRef<T>> {
return services.vaultService.statesForRefs(this).map {
StateAndRef(it.value as TransactionState<T>, it.key)
}
return rpc.vaultQueryBy<T>(QueryCriteria.VaultQueryCriteria(stateRefs = this)).states
}

View File

@ -1,21 +1,23 @@
package net.corda.traderdemo
import com.google.common.util.concurrent.Futures
import net.corda.client.rpc.notUsed
import net.corda.contracts.CommercialPaper
import net.corda.contracts.asset.Cash
import net.corda.contracts.getCashBalance
import net.corda.core.contracts.Amount
import net.corda.core.contracts.DOLLARS
import net.corda.core.contracts.USD
import net.corda.core.contracts.filterStatesOfType
import net.corda.core.getOrThrow
import net.corda.core.internal.Emoji
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.builder
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.loggerFor
import net.corda.flows.IssuerFlow.IssuanceRequester
import net.corda.node.services.vault.VaultSchemaV1
import net.corda.testing.BOC
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.calculateRandomlySizedAmounts
@ -31,18 +33,18 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
val logger = loggerFor<TraderDemoClientApi>()
}
val cashCount: Int get() {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
return vault.filterStatesOfType<Cash.State>().size
val cashCount: Long get() {
val count = builder { VaultSchemaV1.VaultStates::recordedTime.count() }
val countCriteria = QueryCriteria.VaultCustomQueryCriteria(count)
return rpc.vaultQueryBy<Cash.State>(countCriteria).otherResults.single() as Long
}
val dollarCashBalance: Amount<Currency> get() = rpc.getCashBalance(USD)
val commercialPaperCount: Int get() {
val (vault, vaultUpdates) = rpc.vaultAndUpdates()
vaultUpdates.notUsed()
return vault.filterStatesOfType<CommercialPaper.State>().size
val commercialPaperCount: Long get() {
val count = builder { VaultSchemaV1.VaultStates::recordedTime.count() }
val countCriteria = QueryCriteria.VaultCustomQueryCriteria(count)
return rpc.vaultQueryBy<CommercialPaper.State>(countCriteria).otherResults.single() as Long
}
fun runBuyer(amount: Amount<Currency> = 30000.DOLLARS, anonymous: Boolean = true) {

View File

@ -8,6 +8,7 @@ import net.corda.core.contracts.Issued
import net.corda.core.contracts.PartyAndReference
import net.corda.core.contracts.USD
import net.corda.core.identity.AbstractParty
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.thenMatch
import net.corda.core.utilities.OpaqueBytes
import net.corda.flows.CashFlowCommand
@ -218,14 +219,11 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
val currentNodeVaults = HashMap<AbstractParty, HashMap<AbstractParty, Long>>()
simpleNodes.forEach {
val quantities = HashMap<AbstractParty, Long>()
val (vault, vaultUpdates) = it.proxy.vaultAndUpdates()
vaultUpdates.notUsed()
val vault = it.proxy.vaultQueryBy<Cash.State>().states
vault.forEach {
val state = it.state.data
if (state is Cash.State) {
val issuer = state.amount.token.issuer.party
quantities.put(issuer, (quantities[issuer] ?: 0L) + state.amount.quantity)
}
val issuer = state.amount.token.issuer.party
quantities.put(issuer, (quantities[issuer] ?: 0L) + state.amount.quantity)
}
currentNodeVaults.put(it.info.legalIdentity, quantities)
}

View File

@ -10,6 +10,7 @@ import net.corda.core.contracts.USD
import net.corda.core.flows.FlowException
import net.corda.core.getOrThrow
import net.corda.core.identity.AbstractParty
import net.corda.core.messaging.vaultQueryBy
import net.corda.flows.CashFlowCommand
import net.corda.loadtest.LoadTest
import net.corda.loadtest.NodeConnection
@ -71,15 +72,12 @@ val selfIssueTest = LoadTest<SelfIssueCommand, SelfIssueState>(
gatherRemoteState = { previousState ->
val selfIssueVaults = HashMap<AbstractParty, Long>()
simpleNodes.forEach { connection ->
val (vault, vaultUpdates) = connection.proxy.vaultAndUpdates()
vaultUpdates.notUsed()
val vault = connection.proxy.vaultQueryBy<Cash.State>().states
vault.forEach {
val state = it.state.data
if (state is Cash.State) {
val issuer = state.amount.token.issuer.party
if (issuer == connection.info.legalIdentity as AbstractParty) {
selfIssueVaults.put(issuer, (selfIssueVaults[issuer] ?: 0L) + state.amount.quantity)
}
val issuer = state.amount.token.issuer.party
if (issuer == connection.info.legalIdentity as AbstractParty) {
selfIssueVaults.put(issuer, (selfIssueVaults[issuer] ?: 0L) + state.amount.quantity)
}
}
}