mirror of
https://github.com/corda/corda.git
synced 2025-01-26 06:09:25 +00:00
Clean up semantics of composite clauses
This deprecates the existing composition clauses and adds new better named versions, as well as changing 'AnyOf' to require at least one matching subclase (better matching the name of the clause).
This commit is contained in:
parent
7c0ffc78f8
commit
2efd44d46b
@ -1,39 +1,10 @@
|
||||
package net.corda.core.contracts.clauses
|
||||
|
||||
import net.corda.core.contracts.AuthenticatedObject
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Compose a number of clauses, such that all of the clauses must run for verification to pass.
|
||||
*/
|
||||
// TODO: Rename to AllOf
|
||||
class AllComposition<S : ContractState, C : CommandData, K : Any>(firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
override val clauses = ArrayList<Clause<S, C, K>>()
|
||||
|
||||
init {
|
||||
clauses.add(firstClause)
|
||||
clauses.addAll(remainingClauses)
|
||||
}
|
||||
|
||||
override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> {
|
||||
clauses.forEach { clause ->
|
||||
check(clause.matches(commands)) { "Failed to match clause ${clause}" }
|
||||
}
|
||||
return clauses
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<S>,
|
||||
outputs: List<S>,
|
||||
commands: List<AuthenticatedObject<C>>,
|
||||
groupingKey: K?): Set<C> {
|
||||
return matchedClauses(commands).flatMapTo(HashSet<C>()) { clause ->
|
||||
clause.verify(tx, inputs, outputs, commands, groupingKey)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = "All: $clauses.toList()"
|
||||
}
|
||||
@Deprecated("Use AllOf")
|
||||
class AllComposition<S : ContractState, C : CommandData, K : Any>(firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : AllOf<S, C, K>(firstClause, *remainingClauses)
|
@ -0,0 +1,38 @@
|
||||
package net.corda.core.contracts.clauses
|
||||
|
||||
import net.corda.core.contracts.AuthenticatedObject
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Compose a number of clauses, such that all of the clauses must run for verification to pass.
|
||||
*/
|
||||
open class AllOf<S : ContractState, C : CommandData, K : Any>(firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
override val clauses = ArrayList<Clause<S, C, K>>()
|
||||
|
||||
init {
|
||||
clauses.add(firstClause)
|
||||
clauses.addAll(remainingClauses)
|
||||
}
|
||||
|
||||
override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> {
|
||||
clauses.forEach { clause ->
|
||||
check(clause.matches(commands)) { "Failed to match clause ${clause}" }
|
||||
}
|
||||
return clauses
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<S>,
|
||||
outputs: List<S>,
|
||||
commands: List<AuthenticatedObject<C>>,
|
||||
groupingKey: K?): Set<C> {
|
||||
return matchedClauses(commands).flatMapTo(HashSet<C>()) { clause ->
|
||||
clause.verify(tx, inputs, outputs, commands, groupingKey)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = "All: $clauses.toList()"
|
||||
}
|
@ -1,25 +1,10 @@
|
||||
package net.corda.core.contracts.clauses
|
||||
|
||||
import net.corda.core.contracts.AuthenticatedObject
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Compose a number of clauses, such that any number of the clauses can run.
|
||||
*/
|
||||
// TODO: Rename to AnyOf
|
||||
class AnyComposition<in S : ContractState, C : CommandData, in K : Any>(vararg rawClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
override val clauses: List<Clause<S, C, K>> = rawClauses.asList()
|
||||
|
||||
override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> = clauses.filter { it.matches(commands) }
|
||||
|
||||
override fun verify(tx: TransactionForContract, inputs: List<S>, outputs: List<S>, commands: List<AuthenticatedObject<C>>, groupingKey: K?): Set<C> {
|
||||
return matchedClauses(commands).flatMapTo(HashSet<C>()) { clause ->
|
||||
clause.verify(tx, inputs, outputs, commands, groupingKey)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = "Or: ${clauses.toList()}"
|
||||
}
|
||||
@Deprecated("Use AnyOf instead, although note that any of requires at least one matched clause")
|
||||
class AnyComposition<in S : ContractState, C : CommandData, in K : Any>(vararg rawClauses: Clause<S, C, K>) : AnyOf<S, C, K>(*rawClauses)
|
@ -0,0 +1,28 @@
|
||||
package net.corda.core.contracts.clauses
|
||||
|
||||
import net.corda.core.contracts.AuthenticatedObject
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Compose a number of clauses, such that one or more of the clauses can run.
|
||||
*/
|
||||
open class AnyOf<in S : ContractState, C : CommandData, in K : Any>(vararg rawClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
override val clauses: List<Clause<S, C, K>> = rawClauses.toList()
|
||||
|
||||
override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> {
|
||||
val matched = clauses.filter { it.matches(commands) }
|
||||
require(matched.isNotEmpty()) { "At least one clause must match" }
|
||||
return matched
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract, inputs: List<S>, outputs: List<S>, commands: List<AuthenticatedObject<C>>, groupingKey: K?): Set<C> {
|
||||
return matchedClauses(commands).flatMapTo(HashSet<C>()) { clause ->
|
||||
clause.verify(tx, inputs, outputs, commands, groupingKey)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = "Any: ${clauses.toList()}"
|
||||
}
|
@ -26,7 +26,11 @@ abstract class Clause<in S : ContractState, C : CommandData, in K : Any> {
|
||||
|
||||
/**
|
||||
* Determine the subclauses which will be verified as a result of verifying this clause.
|
||||
*
|
||||
* @throws IllegalStateException if the given commands do not result in a valid execution (for example no match
|
||||
* with [FirstOf]).
|
||||
*/
|
||||
@Throws(IllegalStateException::class)
|
||||
open fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>
|
||||
= listOf(this)
|
||||
|
||||
|
@ -14,6 +14,12 @@ abstract class CompositeClause<in S : ContractState, C : CommandData, in K : Any
|
||||
override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>
|
||||
= matchedClauses(commands).flatMap { it.getExecutionPath(commands) }
|
||||
|
||||
/** Determine which clauses are matched by the supplied commands */
|
||||
/**
|
||||
* Determine which clauses are matched by the supplied commands.
|
||||
*
|
||||
* @throws IllegalStateException if the given commands do not result in a valid execution (for example no match
|
||||
* with [FirstOf]).
|
||||
*/
|
||||
@Throws(IllegalStateException::class)
|
||||
abstract fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>>
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import java.util.*
|
||||
/**
|
||||
* Compose a number of clauses, such that the first match is run, and it errors if none is run.
|
||||
*/
|
||||
// TODO: Rename to FirstOf
|
||||
@Deprecated("Use FirstOf instead")
|
||||
class FirstComposition<S : ContractState, C : CommandData, K : Any>(val firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
companion object {
|
||||
val logger = loggerFor<FirstComposition<*, *, *>>()
|
||||
|
@ -0,0 +1,41 @@
|
||||
package net.corda.core.contracts.clauses
|
||||
|
||||
import net.corda.core.contracts.AuthenticatedObject
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Compose a number of clauses, such that the first match is run, and it errors if none is run.
|
||||
*/
|
||||
class FirstOf<S : ContractState, C : CommandData, K : Any>(val firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
|
||||
companion object {
|
||||
val logger = loggerFor<FirstOf<*, *, *>>()
|
||||
}
|
||||
|
||||
override val clauses = ArrayList<Clause<S, C, K>>()
|
||||
|
||||
/**
|
||||
* Get the single matched clause from the set this composes, based on the given commands. This is provided as
|
||||
* helper method for internal use, rather than using the exposed [matchedClauses] function which unnecessarily
|
||||
* wraps the clause in a list.
|
||||
*/
|
||||
private fun matchedClause(commands: List<AuthenticatedObject<C>>): Clause<S, C, K> {
|
||||
return clauses.firstOrNull { it.matches(commands) } ?: throw IllegalStateException("No delegate clause matched in first composition")
|
||||
}
|
||||
|
||||
override fun matchedClauses(commands: List<AuthenticatedObject<C>>) = listOf(matchedClause(commands))
|
||||
|
||||
init {
|
||||
clauses.add(firstClause)
|
||||
clauses.addAll(remainingClauses)
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract, inputs: List<S>, outputs: List<S>, commands: List<AuthenticatedObject<C>>, groupingKey: K?): Set<C> {
|
||||
return matchedClause(commands).verify(tx, inputs, outputs, commands, groupingKey)
|
||||
}
|
||||
|
||||
override fun toString() = "First: ${clauses.toList()}"
|
||||
}
|
@ -9,12 +9,12 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class AllCompositionTests {
|
||||
class AllOfTests {
|
||||
|
||||
@Test
|
||||
fun minimal() {
|
||||
val counter = AtomicInteger(0)
|
||||
val clause = AllComposition(matchedClause(counter), matchedClause(counter))
|
||||
val clause = AllOf(matchedClause(counter), matchedClause(counter))
|
||||
val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
|
||||
verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>())
|
||||
|
||||
@ -24,7 +24,7 @@ class AllCompositionTests {
|
||||
|
||||
@Test
|
||||
fun `not all match`() {
|
||||
val clause = AllComposition(matchedClause(), unmatchedClause())
|
||||
val clause = AllOf(matchedClause(), unmatchedClause())
|
||||
val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
|
||||
assertFailsWith<IllegalStateException> { verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>()) }
|
||||
}
|
@ -7,12 +7,13 @@ import net.corda.core.crypto.SecureHash
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class AnyCompositionTests {
|
||||
class AnyOfTests {
|
||||
@Test
|
||||
fun minimal() {
|
||||
val counter = AtomicInteger(0)
|
||||
val clause = AnyComposition(matchedClause(counter), matchedClause(counter))
|
||||
val clause = AnyOf(matchedClause(counter), matchedClause(counter))
|
||||
val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
|
||||
verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>())
|
||||
|
||||
@ -23,7 +24,7 @@ class AnyCompositionTests {
|
||||
@Test
|
||||
fun `not all match`() {
|
||||
val counter = AtomicInteger(0)
|
||||
val clause = AnyComposition(matchedClause(counter), unmatchedClause(counter))
|
||||
val clause = AnyOf(matchedClause(counter), unmatchedClause(counter))
|
||||
val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
|
||||
verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>())
|
||||
|
||||
@ -34,11 +35,10 @@ class AnyCompositionTests {
|
||||
@Test
|
||||
fun `none match`() {
|
||||
val counter = AtomicInteger(0)
|
||||
val clause = AnyComposition(unmatchedClause(counter), unmatchedClause(counter))
|
||||
val clause = AnyOf(unmatchedClause(counter), unmatchedClause(counter))
|
||||
val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
|
||||
verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>())
|
||||
|
||||
// Check that we've run the verify() function of neither clause
|
||||
assertEquals(0, counter.get())
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
verifyClause(tx, clause, emptyList<AuthenticatedObject<CommandData>>())
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import net.corda.core.contracts.TransactionForContract
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
internal fun matchedClause(counter: AtomicInteger? = null) = object : Clause<ContractState, CommandData, Unit>() {
|
||||
override val requiredCommands: Set<Class<out CommandData>> = emptySet()
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<ContractState>,
|
||||
outputs: List<ContractState>,
|
||||
|
@ -37,7 +37,7 @@ When writing a contract you need to override the contract's ``verify`` function
|
||||
there is a check if all of transaction's commands were matched. If not, then an exception is raised. This is done to
|
||||
enforce that spurious commands cannot be included in a transaction, ensuring that the transaction is as clear as
|
||||
possible. As an example imagine a transaction with two commands: ``Move`` and ``Issue`` included, with verification written
|
||||
using ``FirstComposition`` on clauses that require single command set. Thus only one of transaction's commands will match
|
||||
using ``FirstOf`` on clauses that require single command set. Thus only one of transaction's commands will match
|
||||
leaving the second unprocessed. It should raise an error - we want to ensure that commands set is minimal to simplify
|
||||
analysis of intent of a transaction.
|
||||
|
||||
@ -47,14 +47,14 @@ An example ``verify`` from ``Obligation`` contract:
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
override fun verify(tx: TransactionForContract) = verifyClause<Commands>(tx, FirstComposition<ContractState, Commands, Unit>(
|
||||
override fun verify(tx: TransactionForContract) = verifyClause<Commands>(tx, FirstOf<ContractState, Commands, Unit>(
|
||||
Clauses.Net<Commands, P>(),
|
||||
Clauses.Group<P>()
|
||||
), tx.commands.select<Obligation.Commands>())
|
||||
|
||||
It takes transaction to be verified, and passes it along with a top-level clause and commands to the ``verifyClause``
|
||||
function. As you can see above we have used ``FirstComposition`` which is a special type of clause, which extends the
|
||||
``CompositeClause`` abstract class (in that particular case, it ensures that either ``Net`` or ``Group`` will run - for explanation see `FirstComposition`_).
|
||||
function. As you can see above we have used ``FirstOf`` which is a special type of clause, which extends the
|
||||
``CompositeClause`` abstract class (in that particular case, it ensures that either ``Net`` or ``Group`` will run - for explanation see `FirstOf`_).
|
||||
It's a type of clause that adds support for encapsulating multiple clauses and defines common behaviour for that composition.
|
||||
There is also a ``GroupClauseVerifier`` special clause, which specifies how to group transaction input/output states
|
||||
together and passes them to adequate clause for further processing.
|
||||
@ -66,37 +66,37 @@ One of the most important concepts of clauses - composition clauses which extend
|
||||
providing a range of ways of assembling clauses together. They define a logic of verification execution specifying which clauses
|
||||
will be run.
|
||||
|
||||
AllComposition
|
||||
~~~~~~~~~~~~~~
|
||||
AllOf
|
||||
~~~~~
|
||||
|
||||
**Description**
|
||||
|
||||
Composes a number of clauses, such that all of the clauses must run for verification to pass.
|
||||
|
||||
.. image:: resources/allCompositionChart.png
|
||||
.. image:: resources/allOfChart.png
|
||||
|
||||
Short description:
|
||||
|
||||
- ``AllComposition`` holds clauses *Cl1,..,Cl5*.
|
||||
- Check if all clauses that compose ``AllComposition`` have associated commands in a command set - if not, verification fails.
|
||||
- ``AllOf`` holds clauses *Cl1,..,Cl5*.
|
||||
- Check if all clauses that compose ``AllOf`` have associated commands in a command set - if not, verification fails.
|
||||
- After successful check runs verification logic specific for every clause *Cl1,..,Cl5* from that composition.
|
||||
|
||||
**Usage**
|
||||
|
||||
See code in `GroupClauseVerifier`_.
|
||||
|
||||
AnyComposition
|
||||
~~~~~~~~~~~~~~
|
||||
AnyOf
|
||||
~~~~~
|
||||
|
||||
**Description**
|
||||
|
||||
Composes a number of clauses, such that 0 or more of the clauses can be run.
|
||||
Composes a number of clauses, such that 1 or more of the clauses can be run.
|
||||
|
||||
.. image:: resources/anyCompositionChart.png
|
||||
.. image:: resources/anyOfChart.png
|
||||
|
||||
Short description:
|
||||
|
||||
- Checks if zero or more clauses that compose AnyComposition have associated commands in a command set.
|
||||
- Checks if one or more clauses that compose AnyOf have associated commands in a command set.
|
||||
- After success runs verification logic specific for every *matched* (in this case *Cl2, Cl4, Cl5*) clause from composition.
|
||||
|
||||
**Usage**
|
||||
@ -108,7 +108,7 @@ Example from ``CommercialPaper.kt``:
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Terms>>(
|
||||
AnyComposition(
|
||||
AnyOf(
|
||||
Redeem(),
|
||||
Move(),
|
||||
Issue())) {
|
||||
@ -116,14 +116,14 @@ Example from ``CommercialPaper.kt``:
|
||||
= tx.groupStates<State, Issued<Terms>> { it.token }
|
||||
}
|
||||
|
||||
FirstComposition
|
||||
~~~~~~~~~~~~~~~~
|
||||
FirstOf
|
||||
~~~~~~~
|
||||
|
||||
**Description**
|
||||
|
||||
Composes a number of clauses, such that the first match is run, and it errors if none is run.
|
||||
|
||||
.. image:: resources/firstCompositionChart.png
|
||||
.. image:: resources/firstOfChart.png
|
||||
|
||||
Short description:
|
||||
|
||||
@ -168,13 +168,13 @@ grouped input and output states with a grouping key used for each group. Example
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
class Group<P> : GroupClauseVerifier<State<P>, Commands, Issued<Terms<P>>>(
|
||||
AllComposition(
|
||||
AllOf(
|
||||
NoZeroSizedOutputs<State<P>, Commands, Terms<P>>(),
|
||||
FirstComposition(
|
||||
FirstOf(
|
||||
SetLifecycle<P>(),
|
||||
AllComposition(
|
||||
AllOf(
|
||||
VerifyLifecycle<State<P>, Commands, Issued<Terms<P>>, P>(),
|
||||
FirstComposition(
|
||||
FirstOf(
|
||||
Settle<P>(),
|
||||
Issue(),
|
||||
ConserveAmount()
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@ -36,20 +36,20 @@ to be considered valid. We refer to a clause as being "matched" when the transac
|
||||
in question to trigger. Meanwhile, we talk about a clause "verifying" when its ``verify()`` function returns ``True``.
|
||||
|
||||
As an example, let's say we want a transaction to be valid only when every single one of its clauses matches and verifies. We implement this
|
||||
by wrapping the individual clauses into an ``AllComposition`` composite clause, which ensures that a transaction is
|
||||
by wrapping the individual clauses into an ``AllOf`` composite clause, which ensures that a transaction is
|
||||
only considered valid if all of its clauses are both matched and verify.
|
||||
|
||||
There are two other basic composite clauses that you should be aware of:
|
||||
|
||||
* ``AnyComposition``, whereby any number of clauses (0+) may match, but each matched clause must verify
|
||||
* ``FirstComposition``, whereby at least one clause must match, and the first such clause must verify
|
||||
* ``AnyOf``, whereby 1 or more clauses may match, and every matched clause must verify
|
||||
* ``FirstOf``, whereby at least one clause must match, and the first such clause must verify
|
||||
|
||||
In turn, composite clauses are themselves ``Clause`` s, and can, for example, be wrapped in the special ``GroupClauseVerifier`` grouping clause.
|
||||
For ``CommercialPaper``, this would look as follows:
|
||||
|
||||
.. image:: resources/commPaperClauses.png
|
||||
|
||||
For this tutorial, we will be using ``GroupClauseVerifier`` and ``AnyComposition``. Since it's important to understand how these work,
|
||||
For this tutorial, we will be using ``GroupClauseVerifier`` and ``AnyOf``. Since it's important to understand how these work,
|
||||
charts showing their execution and other details can be found in :doc:`clauses`.
|
||||
|
||||
.. _verify_ref:
|
||||
@ -225,7 +225,7 @@ its subclauses (wrapped move, issue, redeem). "Any" in this case means that it w
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Terms>>(
|
||||
AnyComposition(
|
||||
AnyOf(
|
||||
Redeem(),
|
||||
Move(),
|
||||
Issue())) {
|
||||
@ -237,7 +237,7 @@ its subclauses (wrapped move, issue, redeem). "Any" in this case means that it w
|
||||
|
||||
class Group extends GroupClauseVerifier<State, Commands, State> {
|
||||
public Group() {
|
||||
super(new AnyComposition<>(
|
||||
super(new AnyOf<>(
|
||||
new Clauses.Redeem(),
|
||||
new Clauses.Move(),
|
||||
new Clauses.Issue()
|
||||
|
@ -131,10 +131,10 @@ public class JavaCommercialPaper implements Contract {
|
||||
// warning.
|
||||
@SuppressWarnings("unchecked")
|
||||
Group() {
|
||||
super(new AnyComposition<>(
|
||||
new Clauses.Redeem(),
|
||||
new Clauses.Move(),
|
||||
new Clauses.Issue()
|
||||
super(new AnyOf<>(
|
||||
new Clauses.Redeem(),
|
||||
new Clauses.Move(),
|
||||
new Clauses.Issue()
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package net.corda.contracts
|
||||
import net.corda.contracts.asset.sumCashBy
|
||||
import net.corda.contracts.clause.AbstractIssue
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.clauses.AnyComposition
|
||||
import net.corda.core.contracts.clauses.AnyOf
|
||||
import net.corda.core.contracts.clauses.Clause
|
||||
import net.corda.core.contracts.clauses.GroupClauseVerifier
|
||||
import net.corda.core.contracts.clauses.verifyClause
|
||||
@ -103,10 +103,10 @@ class CommercialPaper : Contract {
|
||||
|
||||
interface Clauses {
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Terms>>(
|
||||
AnyComposition(
|
||||
Redeem(),
|
||||
Move(),
|
||||
Issue())) {
|
||||
AnyOf(
|
||||
Redeem(),
|
||||
Move(),
|
||||
Issue())) {
|
||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<State, Issued<Terms>>>
|
||||
= tx.groupStates<State, Issued<Terms>> { it.token }
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import net.corda.contracts.clause.AbstractConserveAmount
|
||||
import net.corda.contracts.clause.AbstractIssue
|
||||
import net.corda.contracts.clause.NoZeroSizedOutputs
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.clauses.AllComposition
|
||||
import net.corda.core.contracts.clauses.FirstComposition
|
||||
import net.corda.core.contracts.clauses.AllOf
|
||||
import net.corda.core.contracts.clauses.FirstOf
|
||||
import net.corda.core.contracts.clauses.GroupClauseVerifier
|
||||
import net.corda.core.contracts.clauses.verifyClause
|
||||
import net.corda.core.crypto.*
|
||||
@ -56,9 +56,9 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
= commands.select<Cash.Commands>()
|
||||
|
||||
interface Clauses {
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Currency>>(AllComposition<State, Commands, Issued<Currency>>(
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Currency>>(AllOf<State, Commands, Issued<Currency>>(
|
||||
NoZeroSizedOutputs<State, Commands, Currency>(),
|
||||
FirstComposition<State, Commands, Issued<Currency>>(
|
||||
FirstOf<State, Commands, Issued<Currency>>(
|
||||
Issue(),
|
||||
ConserveAmount())
|
||||
)
|
||||
|
@ -4,7 +4,7 @@ import net.corda.contracts.clause.AbstractConserveAmount
|
||||
import net.corda.contracts.clause.AbstractIssue
|
||||
import net.corda.contracts.clause.NoZeroSizedOutputs
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.clauses.AnyComposition
|
||||
import net.corda.core.contracts.clauses.AnyOf
|
||||
import net.corda.core.contracts.clauses.GroupClauseVerifier
|
||||
import net.corda.core.contracts.clauses.verifyClause
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
@ -62,7 +62,7 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
|
||||
* Grouping clause to extract input and output states into matched groups and then run a set of clauses over
|
||||
* each group.
|
||||
*/
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Commodity>>(AnyComposition(
|
||||
class Group : GroupClauseVerifier<State, Commands, Issued<Commodity>>(AnyOf(
|
||||
NoZeroSizedOutputs<State, Commands, Commodity>(),
|
||||
Issue(),
|
||||
ConserveAmount())) {
|
||||
|
@ -47,13 +47,13 @@ class Obligation<P> : Contract {
|
||||
* Parent clause for clauses that operate on grouped states (those which are fungible).
|
||||
*/
|
||||
class Group<P> : GroupClauseVerifier<State<P>, Commands, Issued<Terms<P>>>(
|
||||
AllComposition(
|
||||
AllOf(
|
||||
NoZeroSizedOutputs<State<P>, Commands, Terms<P>>(),
|
||||
FirstComposition(
|
||||
FirstOf(
|
||||
SetLifecycle<P>(),
|
||||
AllComposition(
|
||||
AllOf(
|
||||
VerifyLifecycle<State<P>, Commands, Issued<Terms<P>>, P>(),
|
||||
FirstComposition(
|
||||
FirstOf(
|
||||
Settle<P>(),
|
||||
Issue(),
|
||||
ConserveAmount()
|
||||
@ -364,7 +364,7 @@ class Obligation<P> : Contract {
|
||||
data class Exit<P>(override val amount: Amount<Issued<Terms<P>>>) : Commands, FungibleAsset.Commands.Exit<Terms<P>>
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract) = verifyClause<Commands>(tx, FirstComposition<ContractState, Commands, Unit>(
|
||||
override fun verify(tx: TransactionForContract) = verifyClause<Commands>(tx, FirstOf<ContractState, Commands, Unit>(
|
||||
Clauses.Net<Commands, P>(),
|
||||
Clauses.Group<P>()
|
||||
), tx.commands.select<Obligation.Commands>())
|
||||
|
@ -9,7 +9,7 @@ import java.math.BigDecimal
|
||||
* Specifies the contract between two parties that trade an OpenGamma IRS. Currently can only agree to trade.
|
||||
*/
|
||||
data class OGTrade(override val legalContractReference: SecureHash = SecureHash.sha256("OGTRADE.KT")) : Contract {
|
||||
override fun verify(tx: TransactionForContract) = verifyClause(tx, AllComposition(Clauses.Timestamped(), Clauses.Group()), tx.commands.select<Commands>())
|
||||
override fun verify(tx: TransactionForContract) = verifyClause(tx, AllOf(Clauses.Timestamped(), Clauses.Group()), tx.commands.select<Commands>())
|
||||
|
||||
interface Commands : CommandData {
|
||||
class Agree : TypeOnlyCommandData(), Commands // Both sides agree to trade
|
||||
@ -28,7 +28,7 @@ data class OGTrade(override val legalContractReference: SecureHash = SecureHash.
|
||||
}
|
||||
}
|
||||
|
||||
class Group : GroupClauseVerifier<IRSState, Commands, UniqueIdentifier>(AnyComposition(Agree())) {
|
||||
class Group : GroupClauseVerifier<IRSState, Commands, UniqueIdentifier>(AnyOf(Agree())) {
|
||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<IRSState, UniqueIdentifier>>
|
||||
// Group by Trade ID for in / out states
|
||||
= tx.groupStates() { state -> state.linearId }
|
||||
|
@ -10,7 +10,7 @@ import net.corda.core.crypto.SecureHash
|
||||
* of the portfolio arbitrarily.
|
||||
*/
|
||||
data class PortfolioSwap(override val legalContractReference: SecureHash = SecureHash.sha256("swordfish")) : Contract {
|
||||
override fun verify(tx: TransactionForContract) = verifyClause(tx, AllComposition(Clauses.Timestamped(), Clauses.Group()), tx.commands.select<Commands>())
|
||||
override fun verify(tx: TransactionForContract) = verifyClause(tx, AllOf(Clauses.Timestamped(), Clauses.Group()), tx.commands.select<Commands>())
|
||||
|
||||
interface Commands : CommandData {
|
||||
class Agree : TypeOnlyCommandData(), Commands // Both sides agree to portfolio
|
||||
@ -30,7 +30,7 @@ data class PortfolioSwap(override val legalContractReference: SecureHash = Secur
|
||||
}
|
||||
}
|
||||
|
||||
class Group : GroupClauseVerifier<PortfolioState, Commands, UniqueIdentifier>(FirstComposition(Agree(), Update())) {
|
||||
class Group : GroupClauseVerifier<PortfolioState, Commands, UniqueIdentifier>(FirstOf(Agree(), Update())) {
|
||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<PortfolioState, UniqueIdentifier>>
|
||||
// Group by Trade ID for in / out states
|
||||
= tx.groupStates() { state -> state.linearId }
|
||||
|
Loading…
x
Reference in New Issue
Block a user