Add netting support structures

Add NetType enum for use in contracts which deal with netting
Add BilateralNettingState interface
Add support for more complex issued things
This commit is contained in:
Ross Nicoll 2016-06-21 11:47:37 +01:00
parent 7ee6bd05ce
commit d24ec06b40
6 changed files with 50 additions and 9 deletions

View File

@ -62,6 +62,9 @@ class Cash : FungibleAsset<Currency>() {
override val participants: List<PublicKey>
get() = listOf(owner)
override fun move(amount: Amount<Issued<Currency>>, owner: PublicKey): FungibleAsset.State<Currency>
= copy(amount = amount, owner = owner)
override fun toString() = "${Emoji.bagOfCash}Cash($amount at $deposit owned by ${owner.toStringShort()})"
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))

View File

@ -31,9 +31,9 @@ class InsufficientBalanceException(val amountMissing: Amount<Currency>) : Except
*/
abstract class FungibleAsset<T> : Contract {
/** A state representing a cash claim against some party */
interface State<T> : FungibleAssetState<T> {
interface State<T> : FungibleAssetState<T, Issued<T>> {
/** Where the underlying currency backing this ledger entry can be found (propagated) */
override val deposit: PartyAndReference
val deposit: PartyAndReference
override val amount: Amount<Issued<T>>
/** There must be a MoveCommand signed by this key to claim the amount */
override val owner: PublicKey

View File

@ -1,16 +1,15 @@
package com.r3corda.contracts.cash
import com.r3corda.core.contracts.Amount
import com.r3corda.core.contracts.OwnableState
import com.r3corda.core.contracts.PartyAndReference
import com.r3corda.core.contracts.Issued
import com.r3corda.core.contracts.OwnableState
import java.security.PublicKey
/**
* Common elements of cash contract states.
*/
interface FungibleAssetState<T> : OwnableState {
val issuanceDef: Issued<T>
/** Where the underlying currency backing this ledger entry can be found (propagated) */
val deposit: PartyAndReference
interface FungibleAssetState<T, I> : OwnableState {
val issuanceDef: I
val amount: Amount<Issued<T>>
fun move(amount: Amount<Issued<T>>, owner: PublicKey): FungibleAssetState<T, I>
}

View File

@ -30,7 +30,7 @@ val Int.SWISS_FRANCS: Amount<Currency> get() = Amount(this.toLong() * 100, CHF)
val Double.DOLLARS: Amount<Currency> get() = Amount((this * 100).toLong(), USD)
infix fun Currency.`issued by`(deposit: PartyAndReference) : Issued<Currency> = Issued<Currency>(deposit, this)
infix fun Amount<Currency>.`issued by`(deposit: PartyAndReference) : Amount<Issued<Currency>> = Amount(quantity, token `issued by` deposit)
infix fun <T> Amount<T>.`issued by`(deposit: PartyAndReference) : Amount<Issued<T>> = Amount(quantity, Issued<T>(deposit, this.token))
//// Requirements /////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -399,3 +399,24 @@ fun calculateDaysBetween(startDate: LocalDate,
else -> TODO("Can't calculate days using convention $dcbDay / $dcbYear")
}
}
/**
* Enum for the types of netting that can be applied to state objects. Exact behaviour
* for each type of netting is left to the contract to determine.
*/
enum class NetType {
/**
* Close-out netting applies where one party is bankrupt or otherwise defaults (exact terms are contract specific),
* and allows their counterparty to net obligations without requiring approval from all parties. For example, if
* Bank A owes Bank B £1m, and Bank B owes Bank A £1m, in the case of Bank B defaulting this would enable Bank A
* to net out the two obligations to zero, rather than being legally obliged to pay £1m without any realistic
* expectation of the debt to them being paid. Realistically this is limited to bilateral netting, to simplify
* determining which party must sign the netting transaction.
*/
CLOSE_OUT,
/**
* "Payment" is used to refer to conventional netting, where all parties must confirm the netting transaction. This
* can be a multilateral netting transaction, and may be created by a central clearing service.
*/
PAYMENT
}

View File

@ -18,6 +18,23 @@ interface NamedByHash {
val id: SecureHash
}
/**
* Interface for state objects that support being netted with other state objects.
*/
interface BilateralNettableState<T: BilateralNettableState<T>> {
/**
* Returns an object used to determine if two states can be subject to close-out netting. If two states return
* equal objects, they can be close out netted together.
*/
val bilateralNetState: Any
/**
* Perform bilateral netting of this state with another state. The two states must be compatible (as in
* bilateralNetState objects are equal).
*/
fun net(other: T): T
}
/**
* A contract state (or just "state") contains opaque data used by a contract program. It can be thought of as a disk
* file that the program can use to persist data across transactions. States are immutable: once created they are never
@ -233,6 +250,7 @@ data class Command(val value: CommandData, val signers: List<PublicKey>) {
}
/** A common issue command, to enforce that issue commands have a nonce value. */
// TODO: Revisit use of nonce values - should this be part of the TX rather than the command perhaps?
interface IssueCommand : CommandData {
val nonce: Long
}