dezzeus
dezzeus

Reputation: 200

How to scatter a FilteredTransaction based on counter-parties

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) LinearStates (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 LinearStates 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

Answers (1)

Joel
Joel

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 LinearStates):

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 TwoPartyStates 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

Related Questions