support multiple output states

This commit is contained in:
sofusmortensen 2016-06-07 21:15:24 +02:00
parent be397881a9
commit 7438fc2297
5 changed files with 48 additions and 6 deletions

View File

@ -38,22 +38,40 @@ class GenericContract : Contract {
val cmd = tx.commands.requireSingleCommand<GenericContract.Commands>()
val outState = tx.outStates.single() as State
val value = cmd.value
when (value) {
is Commands.Action -> {
val inState = tx.inStates.single() as State
val actions = actions(inState.details)
requireThat {
"action must be defined" by ( actions.containsKey(value.name) )
"action must be authorized" by ( cmd.signers.any { actions[ value.name ]!!.actors.any { party -> party.owningKey == it } } )
"output state must match action result state" by ( actions[ value.name ]!!.kontract.equals(outState.details))
"condition must be met" by ( true ) // todo
}
when (tx.outStates.size) {
1 -> {
val outState = tx.outStates.single() as State
requireThat {
"output state must match action result state" by (actions[value.name]!!.kontract.equals(outState.details))
}
}
0 -> throw IllegalArgumentException("must have at least one out state")
else -> {
var allContracts = And( tx.outStates.map { (it as State).details }.toSet() )
requireThat {
"output states must match action result state" by (actions[value.name]!!.kontract.equals(allContracts))
}
}
}
}
is Commands.Issue -> {
val outState = tx.outStates.single() as State
requireThat {
"the transaction is signed by all involved parties" by ( liableParties(outState.details).all { it in cmd.signers } )
"the transaction has no input states" by tx.inStates.isEmpty()

View File

@ -22,7 +22,7 @@ data class Transfer(val amount: Observable<Long>, val currency: Currency, val fr
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(amount.pennies), amount.token, from, to)
}
data class And(val kontracts: Array<Kontract>) : Kontract
data class And(val kontracts: Set<Kontract>) : Kontract
//

View File

@ -13,7 +13,7 @@ val Int.K: Long get() = this.toLong() * 1000
val zero = Zero()
infix fun Kontract.and(kontract: Kontract) = And( arrayOf(this, kontract) )
infix fun Kontract.and(kontract: Kontract) = And( setOf(this, kontract) )
infix fun Action.or(kontract: Action) = Or( arrayOf(this, kontract) )
infix fun Or.or(kontract: Action) = Or( this.contracts.plusElement( kontract ) )
infix fun Or.or(ors: Or) = Or( this.contracts.plus(ors.contracts) )

View File

@ -19,7 +19,7 @@ class ContractBuilder {
when (contracts.size) {
0 -> zero
1 -> contracts[0]
else -> And(contracts.toTypedArray())
else -> And(contracts.toSet())
}
}

View File

@ -18,6 +18,13 @@ class FXSwap {
}
}
val transfer1 = kontract { wileECoyote.gives(roadRunner, 1200.K*USD) }
val transfer2 = kontract { roadRunner.gives(wileECoyote, 1.M*EUR) }
val outState1 = GenericContract.State( DUMMY_NOTARY, transfer1 )
val outState2 = GenericContract.State( DUMMY_NOTARY, transfer2 )
val inState = GenericContract.State( DUMMY_NOTARY, contract)
@Test
@ -43,4 +50,21 @@ class FXSwap {
}
}
@Test
fun `execute`() {
transaction {
input { inState }
output { outState1 }
output { outState2 }
tweak {
arg(wileECoyote.owningKey) { GenericContract.Commands.Action("some undefined name") }
this `fails requirement` "action must be defined"
}
arg(wileECoyote.owningKey) { GenericContract.Commands.Action("execute") }
this.accepts()
}
}
}