All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.corda.contracts.clause.Net.kt Maven / Gradle / Ivy

There is a newer version: 0.12.1
Show newest version
package net.corda.contracts.clause

import com.google.common.annotations.VisibleForTesting
import net.corda.contracts.asset.Obligation
import net.corda.contracts.asset.extractAmountsDue
import net.corda.contracts.asset.sumAmountsDue
import net.corda.core.contracts.*
import net.corda.core.contracts.clauses.Clause
import net.corda.core.crypto.CompositeKey

/**
 * Common interface for the state subsets used when determining nettability of two or more states. Exposes the
 * underlying issued thing.
 */
interface NetState

{ val template: Obligation.Terms

} /** * Subset of state, containing the elements which must match for two obligation transactions to be nettable. * If two obligation state objects produce equal bilateral net states, they are considered safe to net directly. * Bilateral states are used in close-out netting. */ data class BilateralNetState

( val partyKeys: Set, override val template: Obligation.Terms

) : NetState

/** * Subset of state, containing the elements which must match for two or more obligation transactions to be candidates * for netting (this does not include the checks to enforce that everyone's amounts received are the same at the end, * which is handled under the verify() function). * In comparison to [BilateralNetState], this doesn't include the parties' keys, as ensuring balances match on * input and output is handled elsewhere. * Used in cases where all parties (or their proxies) are signing, such as central clearing. */ data class MultilateralNetState

( override val template: Obligation.Terms

) : NetState

/** * Clause for netting contract states. Currently only supports obligation contract. */ // TODO: Make this usable for any nettable contract states open class NetClause : Clause() { override val requiredCommands: Set> = setOf(Obligation.Commands.Net::class.java) @Suppress("ConvertLambdaToReference") override fun verify(tx: TransactionForContract, inputs: List, outputs: List, commands: List>, groupingKey: Unit?): Set { val matchedCommands: List> = commands.filter { it.value is NetCommand } val command = matchedCommands.requireSingleCommand() val groups = when (command.value.type) { NetType.CLOSE_OUT -> tx.groupStates { it: Obligation.State

-> it.bilateralNetState } NetType.PAYMENT -> tx.groupStates { it: Obligation.State

-> it.multilateralNetState } } for ((groupInputs, groupOutputs, key) in groups) { verifyNetCommand(groupInputs, groupOutputs, command, key) } return matchedCommands.map { it.value }.toSet() } /** * Verify a netting command. This handles both close-out and payment netting. */ @VisibleForTesting fun verifyNetCommand(inputs: List>, outputs: List>, command: AuthenticatedObject, netState: NetState

) { val template = netState.template // Create two maps of balances from obligors to beneficiaries, one for input states, the other for output states. val inputBalances = extractAmountsDue(template, inputs) val outputBalances = extractAmountsDue(template, outputs) // Sum the columns of the matrices. This will yield the net amount payable to/from each party to/from all other participants. // The two summaries must match, reflecting that the amounts owed match on both input and output. requireThat { "all input states use the same template" by (inputs.all { it.template == template }) "all output states use the same template" by (outputs.all { it.template == template }) "amounts owed on input and output must match" by (sumAmountsDue(inputBalances) == sumAmountsDue(outputBalances)) } // TODO: Handle proxies nominated by parties, i.e. a central clearing service val involvedParties = inputs.map { it.beneficiary }.union(inputs.map { it.obligor.owningKey }).toSet() when (command.value.type) { // For close-out netting, allow any involved party to sign NetType.CLOSE_OUT -> require(command.signers.intersect(involvedParties).isNotEmpty()) { "any involved party has signed" } // Require signatures from all parties (this constraint can be changed for other contracts, and is used as a // placeholder while exact requirements are established), or fail the transaction. NetType.PAYMENT -> require(command.signers.containsAll(involvedParties)) { "all involved parties have signed" } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy