Reputation: 200
I have a possibly non-trivial question regarding the use of FilteredTransactions
; let's see if I'm able to explain it to you…
I have a flow which define a final step in a bigger process; within this flow I have to build a transaction that, among other states (some being consumed, others being changed owner), change a specific party in a list of several two-party (expected to raise to three) LinearState
s (the initiating flow's party is the one being changed; the other is a sort of regulator which does other things).
The trouble is that within the flow there are several of these LinearStates
, each with a potentially different other-party and each of these other parties must (obviously) see only the ones related to them; thus the FilteredTransaction
.
To simplify, you can think of this as a collection of two-party LinearState
s in which one of them is like an owner in an OwnableState
and you – the owner – have to change the ownership.
At the moment I'm not sure about the number of signatures required... I think that the owner one should be enough, but don't take it for granted.
My question is basically a request of help in doing that (possibly without splitting the transaction) on the code side because both the docs and the code documentation are (at the moment) quite poor in this regard (e.g. the IRS demo) and the only other example that I've found (on Slack) uses a session
with a Send
of a FilteredTransaction
(with a filter based on the type of the ContractState
; while I need a filter based on a specific attribute) and the Receive
of a signature
; the former is useless, while the latter doesn't seems catchy nor efficient with several (unknown number ahead of time) sessions used in a sequential order.
What do you suggest ?
Thanks in advance!
Upvotes: 2
Views: 104
Reputation: 23140
Let's use the following as a simple example of a state involving two parties (the logic is the same for more complex LinearState
s):
data class TwoPartyState(val partyOne: Party, val partyTwo: Party) : ContractState {
override val participants = listOf(partyOne, partyTwo)
}
Here is a flow that will filter the transaction to only send to each party the TwoPartyState
s that are relevant to them:
@InitiatingFlow
@StartableByRPC
class ScatterFlow : FlowLogic<Unit>() {
override fun call() {
// TODO: Build the transaction.
val signedTransaction = serviceHub.signInitialTransaction(transactionBuilder)
// We create the flow sessions for all the parties we want to send data to.
val outputs = signedTransaction.toLedgerTransaction(serviceHub).outputsOfType<TwoPartyState>()
val parties = outputs.flatMap { it.participants }
val sessions = mutableMapOf<Party, FlowSession>()
parties.forEach {
if ((it) !in sessions) sessions[it] = initiateFlow(it)
}
// For each session, we filter the transaction to only contain the relevant states.
sessions.forEach { (party, session) ->
val filteredTransaction = signedTransaction.buildFilteredTransaction(Predicate {
when (it) {
is TransactionState<*> -> {
if (it.data !is TwoPartyState) false
else party in (it.data as TwoPartyState).participants
}
else -> false
}
})
session.send(filteredTransaction)
}
}
}
Upvotes: 1