Merged in rnicoll-clause-remove-concrete (pull request #316)

Merge ConcreteClause into Clause
This commit is contained in:
Ross Nicoll 2016-09-01 13:42:56 +01:00
commit 102e3f2048
16 changed files with 44 additions and 59 deletions

View File

@ -142,7 +142,7 @@ public class JavaCommercialPaper implements Contract {
} }
} }
class Move extends ConcreteClause<State, Commands, State> { class Move extends Clause<State, Commands, State> {
@NotNull @NotNull
@Override @Override
public Set<Class<? extends CommandData>> getRequiredCommands() { public Set<Class<? extends CommandData>> getRequiredCommands() {
@ -173,7 +173,7 @@ public class JavaCommercialPaper implements Contract {
} }
} }
class Redeem extends ConcreteClause<State, Commands, State> { class Redeem extends Clause<State, Commands, State> {
@NotNull @NotNull
@Override @Override
public Set<Class<? extends CommandData>> getRequiredCommands() { public Set<Class<? extends CommandData>> getRequiredCommands() {
@ -215,7 +215,7 @@ public class JavaCommercialPaper implements Contract {
} }
} }
class Issue extends ConcreteClause<State, Commands, State> { class Issue extends Clause<State, Commands, State> {
@NotNull @NotNull
@Override @Override
public Set<Class<? extends CommandData>> getRequiredCommands() { public Set<Class<? extends CommandData>> getRequiredCommands() {

View File

@ -107,7 +107,7 @@ class CommercialPaper : Contract {
} }
} }
class Move: ConcreteClause<State, Commands, Issued<Terms>>() { class Move: Clause<State, Commands, Issued<Terms>>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Move::class.java) override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Move::class.java)
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
@ -127,7 +127,7 @@ class CommercialPaper : Contract {
} }
} }
class Redeem(): ConcreteClause<State, Commands, Issued<Terms>>() { class Redeem(): Clause<State, Commands, Issued<Terms>>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Redeem::class.java) override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Redeem::class.java)
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,

View File

@ -454,7 +454,7 @@ class InterestRateSwap() : Contract {
* Common superclass for IRS contract clauses, which defines behaviour on match/no-match, and provides * Common superclass for IRS contract clauses, which defines behaviour on match/no-match, and provides
* helper functions for the clauses. * helper functions for the clauses.
*/ */
abstract class AbstractIRSClause : ConcreteClause<State, Commands, UniqueIdentifier>() { abstract class AbstractIRSClause : Clause<State, Commands, UniqueIdentifier>() {
// These functions may make more sense to use for basket types, but for now let's leave them here // These functions may make more sense to use for basket types, but for now let's leave them here
fun checkLegDates(legs: List<CommonLeg>) { fun checkLegDates(legs: List<CommonLeg>) {
requireThat { requireThat {
@ -502,7 +502,7 @@ class InterestRateSwap() : Contract {
= tx.groupStates() { state -> state.linearId } = tx.groupStates() { state -> state.linearId }
} }
class Timestamped : ConcreteClause<ContractState, Commands, Unit>() { class Timestamped : Clause<ContractState, Commands, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,
outputs: List<ContractState>, outputs: List<ContractState>,

View File

@ -90,7 +90,7 @@ class Obligation<P> : Contract {
/** /**
* Obligation-specific clause for changing the lifecycle of one or more states. * Obligation-specific clause for changing the lifecycle of one or more states.
*/ */
class SetLifecycle<P> : ConcreteClause<State<P>, Commands, Issued<Terms<P>>>() { class SetLifecycle<P> : Clause<State<P>, Commands, Issued<Terms<P>>>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.SetLifecycle::class.java) override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.SetLifecycle::class.java)
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
@ -110,7 +110,7 @@ class Obligation<P> : Contract {
* Obligation-specific clause for settling an outstanding obligation by witnessing * Obligation-specific clause for settling an outstanding obligation by witnessing
* change of ownership of other states to fulfil * change of ownership of other states to fulfil
*/ */
class Settle<P> : ConcreteClause<State<P>, Commands, Issued<Terms<P>>>() { class Settle<P> : Clause<State<P>, Commands, Issued<Terms<P>>>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Settle::class.java) override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Settle::class.java)
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<State<P>>, inputs: List<State<P>>,
@ -199,7 +199,7 @@ class Obligation<P> : Contract {
* any lifecycle change clause, which is the only clause that involve * any lifecycle change clause, which is the only clause that involve
* non-standard lifecycle states on input/output. * non-standard lifecycle states on input/output.
*/ */
class VerifyLifecycle<S: ContractState, C: CommandData, T: Any, P> : ConcreteClause<S, C, T>() { class VerifyLifecycle<S: ContractState, C: CommandData, T: Any, P> : Clause<S, C, T>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<S>, inputs: List<S>,
outputs: List<S>, outputs: List<S>,

View File

@ -5,7 +5,7 @@ import com.r3corda.contracts.asset.InsufficientBalanceException
import com.r3corda.contracts.asset.sumFungibleOrNull import com.r3corda.contracts.asset.sumFungibleOrNull
import com.r3corda.contracts.asset.sumFungibleOrZero import com.r3corda.contracts.asset.sumFungibleOrZero
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.contracts.clauses.ConcreteClause import com.r3corda.core.contracts.clauses.Clause
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import java.security.PublicKey import java.security.PublicKey
import java.util.* import java.util.*
@ -15,7 +15,7 @@ import java.util.*
* Move command is provided, and errors if absent. Must be the last clause under a grouping clause; * Move command is provided, and errors if absent. Must be the last clause under a grouping clause;
* errors on no-match, ends on match. * errors on no-match, ends on match.
*/ */
abstract class AbstractConserveAmount<S : FungibleAsset<T>, C : CommandData, T : Any> : ConcreteClause<S, C, Issued<T>>() { abstract class AbstractConserveAmount<S : FungibleAsset<T>, C : CommandData, T : Any> : Clause<S, C, Issued<T>>() {
/** /**
* Gather assets from the given list of states, sufficient to match or exceed the given amount. * Gather assets from the given list of states, sufficient to match or exceed the given amount.
* *

View File

@ -1,7 +1,7 @@
package com.r3corda.contracts.clause package com.r3corda.contracts.clause
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.contracts.clauses.ConcreteClause import com.r3corda.core.contracts.clauses.Clause
/** /**
* Standard issue clause for contracts that issue fungible assets. * Standard issue clause for contracts that issue fungible assets.
@ -16,7 +16,7 @@ import com.r3corda.core.contracts.clauses.ConcreteClause
abstract class AbstractIssue<in S: ContractState, C: CommandData, T: Any>( abstract class AbstractIssue<in S: ContractState, C: CommandData, T: Any>(
val sum: List<S>.() -> Amount<Issued<T>>, val sum: List<S>.() -> Amount<Issued<T>>,
val sumOrZero: List<S>.(token: Issued<T>) -> Amount<Issued<T>> val sumOrZero: List<S>.(token: Issued<T>) -> Amount<Issued<T>>
) : ConcreteClause<S, C, Issued<T>>() { ) : Clause<S, C, Issued<T>>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<S>, inputs: List<S>,
outputs: List<S>, outputs: List<S>,

View File

@ -5,7 +5,7 @@ import com.r3corda.contracts.asset.Obligation
import com.r3corda.contracts.asset.extractAmountsDue import com.r3corda.contracts.asset.extractAmountsDue
import com.r3corda.contracts.asset.sumAmountsDue import com.r3corda.contracts.asset.sumAmountsDue
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.contracts.clauses.ConcreteClause import com.r3corda.core.contracts.clauses.Clause
import java.security.PublicKey import java.security.PublicKey
/** /**
@ -42,7 +42,7 @@ data class MultilateralNetState<P>(
* Clause for netting contract states. Currently only supports obligation contract. * Clause for netting contract states. Currently only supports obligation contract.
*/ */
// TODO: Make this usable for any nettable contract states // TODO: Make this usable for any nettable contract states
open class NetClause<C: CommandData, P> : ConcreteClause<ContractState, C, Unit>() { open class NetClause<C: CommandData, P> : Clause<ContractState, C, Unit>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(Obligation.Commands.Net::class.java) override val requiredCommands: Set<Class<out CommandData>> = setOf(Obligation.Commands.Net::class.java)
@Suppress("ConvertLambdaToReference") @Suppress("ConvertLambdaToReference")

View File

@ -2,13 +2,13 @@ package com.r3corda.contracts.clause
import com.r3corda.contracts.asset.FungibleAsset import com.r3corda.contracts.asset.FungibleAsset
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.contracts.clauses.ConcreteClause import com.r3corda.core.contracts.clauses.Clause
/** /**
* Clause for fungible asset contracts, which enforces that no output state should have * Clause for fungible asset contracts, which enforces that no output state should have
* a balance of zero. * a balance of zero.
*/ */
open class NoZeroSizedOutputs<in S : FungibleAsset<T>, C : CommandData, T : Any> : ConcreteClause<S, C, Issued<T>>() { open class NoZeroSizedOutputs<in S : FungibleAsset<T>, C : CommandData, T : Any> : Clause<S, C, Issued<T>>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<S>, inputs: List<S>,
outputs: List<S>, outputs: List<S>,

View File

@ -1,6 +1,5 @@
package com.r3corda.core.contracts package com.r3corda.core.contracts
import com.r3corda.core.contracts.clauses.ConcreteClause
import com.r3corda.core.contracts.clauses.Clause import com.r3corda.core.contracts.clauses.Clause
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
@ -218,7 +217,7 @@ interface LinearState: ContractState {
/** /**
* Standard clause to verify the LinearState safety properties. * Standard clause to verify the LinearState safety properties.
*/ */
class ClauseVerifier<S : LinearState>(val stateClass: Class<S>) : ConcreteClause<ContractState, CommandData, Unit>() { class ClauseVerifier<S : LinearState>(val stateClass: Class<S>) : Clause<ContractState, CommandData, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,
outputs: List<ContractState>, outputs: List<ContractState>,

View File

@ -7,22 +7,28 @@ import com.r3corda.core.contracts.TransactionForContract
import com.r3corda.core.utilities.loggerFor import com.r3corda.core.utilities.loggerFor
/** /**
* A clause of a contract, containing a chunk of verification logic. That logic may be delegated to other clauses, or
* provided directly by this clause.
*
* @param S the type of contract state this clause operates on. * @param S the type of contract state this clause operates on.
* @param C a common supertype of commands this clause operates on. * @param C a common supertype of commands this clause operates on.
* @param K the type of the grouping key for states this clause operates on. Use [Unit] if not applicable. * @param K the type of the grouping key for states this clause operates on. Use [Unit] if not applicable.
*
* @see CompositeClause
*/ */
interface Clause<in S : ContractState, C: CommandData, in K : Any> { abstract class Clause<in S : ContractState, C : CommandData, in K : Any> {
companion object { companion object {
val log = loggerFor<Clause<*, *, *>>() val log = loggerFor<Clause<*, *, *>>()
} }
/** Determine whether this clause runs or not */ /** Determine whether this clause runs or not */
val requiredCommands: Set<Class<out CommandData>> open val requiredCommands: Set<Class<out CommandData>> = emptySet()
/** /**
* Determine the subclauses which will be verified as a result of verifying this clause. * Determine the subclauses which will be verified as a result of verifying this clause.
*/ */
fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>> open fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>
= listOf(this)
/** /**
* Verify the transaction matches the conditions from this clause. For example, a "no zero amount output" clause * Verify the transaction matches the conditions from this clause. For example, a "no zero amount output" clause
@ -45,7 +51,7 @@ interface Clause<in S : ContractState, C: CommandData, in K : Any> {
* commands that were not required (for example the Exit command for fungible assets is optional). * commands that were not required (for example the Exit command for fungible assets is optional).
*/ */
@Throws(IllegalStateException::class) @Throws(IllegalStateException::class)
fun verify(tx: TransactionForContract, abstract fun verify(tx: TransactionForContract,
inputs: List<S>, inputs: List<S>,
outputs: List<S>, outputs: List<S>,
commands: List<AuthenticatedObject<C>>, commands: List<AuthenticatedObject<C>>,

View File

@ -6,13 +6,10 @@ import com.r3corda.core.contracts.ContractState
/** /**
* Abstract supertype for clauses which compose other clauses together in some logical manner. * Abstract supertype for clauses which compose other clauses together in some logical manner.
*
* @see ConcreteClause
*/ */
abstract class CompositeClause<in S : ContractState, C: CommandData, in K : Any>: Clause<S, C, K> { abstract class CompositeClause<in S : ContractState, C: CommandData, in K : Any>: Clause<S, C, K>() {
/** List of clauses under this composite clause */ /** List of clauses under this composite clause */
abstract val clauses: List<Clause<S, C, K>> abstract val clauses: List<Clause<S, C, K>>
override val requiredCommands: Set<Class<out CommandData>> = emptySet()
override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>> override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>
= matchedClauses(commands).flatMap { it.getExecutionPath(commands) } = matchedClauses(commands).flatMap { it.getExecutionPath(commands) }
/** Determine which clauses are matched by the supplied commands */ /** Determine which clauses are matched by the supplied commands */

View File

@ -1,17 +0,0 @@
package com.r3corda.core.contracts.clauses
import com.r3corda.core.contracts.AuthenticatedObject
import com.r3corda.core.contracts.CommandData
import com.r3corda.core.contracts.ContractState
/**
* Abstract supertype for clauses which provide their own verification logic, rather than delegating to subclauses.
* By default these clauses are always matched (they have no required commands).
*
* @see CompositeClause
*/
abstract class ConcreteClause<in S : ContractState, C: CommandData, in T : Any>: Clause<S, C, T> {
override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>
= listOf(this)
override val requiredCommands: Set<Class<out CommandData>> = emptySet()
}

View File

@ -6,7 +6,7 @@ import com.r3corda.core.contracts.ContractState
import com.r3corda.core.contracts.TransactionForContract import com.r3corda.core.contracts.TransactionForContract
import java.util.* import java.util.*
abstract class GroupClauseVerifier<S : ContractState, C : CommandData, K : Any>(val clause: Clause<S, C, K>) : ConcreteClause<ContractState, C, Unit>() { abstract class GroupClauseVerifier<S : ContractState, C : CommandData, K : Any>(val clause: Clause<S, C, K>) : Clause<ContractState, C, Unit>() {
abstract fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<S, K>> abstract fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<S, K>>
override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>> override fun getExecutionPath(commands: List<AuthenticatedObject<C>>): List<Clause<*, *, *>>

View File

@ -6,7 +6,7 @@ import com.r3corda.core.contracts.ContractState
import com.r3corda.core.contracts.TransactionForContract import com.r3corda.core.contracts.TransactionForContract
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
internal fun matchedClause(counter: AtomicInteger? = null) = object : ConcreteClause<ContractState, CommandData, Unit>() { internal fun matchedClause(counter: AtomicInteger? = null) = object : Clause<ContractState, CommandData, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,
outputs: List<ContractState>, outputs: List<ContractState>,
@ -17,7 +17,7 @@ internal fun matchedClause(counter: AtomicInteger? = null) = object : ConcreteCl
} }
/** A clause that can never be matched */ /** A clause that can never be matched */
internal fun unmatchedClause(counter: AtomicInteger? = null) = object : ConcreteClause<ContractState, CommandData, Unit>() { internal fun unmatchedClause(counter: AtomicInteger? = null) = object : Clause<ContractState, CommandData, Unit>() {
override val requiredCommands: Set<Class<out CommandData>> = setOf(object: CommandData {}.javaClass) override val requiredCommands: Set<Class<out CommandData>> = setOf(object: CommandData {}.javaClass)
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,

View File

@ -12,7 +12,7 @@ class VerifyClausesTests {
/** Very simple check that the function doesn't error when given any clause */ /** Very simple check that the function doesn't error when given any clause */
@Test @Test
fun minimal() { fun minimal() {
val clause = object : ConcreteClause<ContractState, CommandData, Unit>() { val clause = object : Clause<ContractState, CommandData, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,
outputs: List<ContractState>, outputs: List<ContractState>,
@ -24,7 +24,7 @@ class VerifyClausesTests {
@Test @Test
fun errorSuperfluousCommands() { fun errorSuperfluousCommands() {
val clause = object : ConcreteClause<ContractState, CommandData, Unit>() { val clause = object : Clause<ContractState, CommandData, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<ContractState>, inputs: List<ContractState>,
outputs: List<ContractState>, outputs: List<ContractState>,

View File

@ -64,10 +64,10 @@ Clauses
------- -------
We'll tackle the inner clauses that contain the bulk of the verification logic, first, and the clause which handles We'll tackle the inner clauses that contain the bulk of the verification logic, first, and the clause which handles
grouping of input/output states later. The clauses must implement the ``Clause`` interface, which defines grouping of input/output states later. The clauses must extend the ``Clause`` abstract class, which defines
the ``verify`` function, and the ``requiredCommands`` property used to determine the conditions under which a clause the ``verify`` function, and the ``requiredCommands`` property used to determine the conditions under which a clause
is triggered. Normally clauses would extend ``ConcreteClause`` which provides defaults suitable for a clause which is triggered. Composite clauses should extend the ``CompositeClause`` abstract class, which extends ``Clause`` to
verifies transactions, rather than delegating to other clauses. add support for wrapping around multiple clauses.
The ``verify`` function defined in the ``Clause`` interface is similar to the conventional ``Contract`` verification The ``verify`` function defined in the ``Clause`` interface is similar to the conventional ``Contract`` verification
function, although it adds new parameters and returns the set of commands which it has processed. Normally this returned function, although it adds new parameters and returns the set of commands which it has processed. Normally this returned
@ -80,7 +80,7 @@ The ``Move`` clause for the commercial paper contract is relatively simple, so w
.. sourcecode:: kotlin .. sourcecode:: kotlin
class Move: ConcreteClause<State, Commands, Issued<Terms>>() { class Move: Clause<State, Commands, Issued<Terms>>() {
override val requiredCommands: Set<Class<out CommandData>> override val requiredCommands: Set<Class<out CommandData>>
get() = setOf(Commands.Move::class.java) get() = setOf(Commands.Move::class.java)
@ -103,7 +103,7 @@ The ``Move`` clause for the commercial paper contract is relatively simple, so w
.. sourcecode:: java .. sourcecode:: java
class Move extends ConcreteClause<State, Commands, State> { class Move extends Clause<State, Commands, State> {
@NotNull @NotNull
@Override @Override
public Set<Class<? extends CommandData>> getRequiredCommands() { public Set<Class<? extends CommandData>> getRequiredCommands() {