mirror of
https://github.com/corda/corda.git
synced 2025-01-05 12:44:21 +00:00
added timestamp check
This commit is contained in:
parent
c3bf914d30
commit
d5172ea2d0
@ -47,6 +47,7 @@ class UniversalContract : Contract {
|
|||||||
val actions = actions(inState.details)
|
val actions = actions(inState.details)
|
||||||
|
|
||||||
requireThat {
|
requireThat {
|
||||||
|
"action must be timestamped" by ( tx.timestamp != null )
|
||||||
"action must be defined" by ( actions.containsKey(value.name) )
|
"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 } } )
|
"action must be authorized" by ( cmd.signers.any { actions[ value.name ]!!.actors.any { party -> party.owningKey == it } } )
|
||||||
"condition must be met" by ( true ) // todo
|
"condition must be met" by ( true ) // todo
|
||||||
|
@ -2,8 +2,10 @@ package com.r3corda.contracts.universal
|
|||||||
|
|
||||||
import com.r3corda.core.testing.DUMMY_NOTARY
|
import com.r3corda.core.testing.DUMMY_NOTARY
|
||||||
import com.r3corda.core.testing.DUMMY_NOTARY_KEY
|
import com.r3corda.core.testing.DUMMY_NOTARY_KEY
|
||||||
|
import com.r3corda.core.testing.TEST_TX_TIME
|
||||||
import com.r3corda.core.testing.transaction
|
import com.r3corda.core.testing.transaction
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sofusmortensen on 01/06/16.
|
* Created by sofusmortensen on 01/06/16.
|
||||||
@ -11,6 +13,8 @@ import org.junit.Test
|
|||||||
|
|
||||||
class FXSwap {
|
class FXSwap {
|
||||||
|
|
||||||
|
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||||
|
|
||||||
val contract =
|
val contract =
|
||||||
(roadRunner or wileECoyote).may {
|
(roadRunner or wileECoyote).may {
|
||||||
"execute".givenThat(after("01/09/2017")) {
|
"execute".givenThat(after("01/09/2017")) {
|
||||||
@ -25,6 +29,13 @@ class FXSwap {
|
|||||||
val outState1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer1 )
|
val outState1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer1 )
|
||||||
val outState2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer2 )
|
val outState2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer2 )
|
||||||
|
|
||||||
|
val transferBad1 = arrange { wileECoyote.gives(roadRunner, 1200.K*GBP) } // wrong currency
|
||||||
|
val transferBad2 = arrange { roadRunner.gives(wileECoyote, 900.K*EUR) } // wrong amount
|
||||||
|
val transferBad3 = arrange { wileECoyote.gives(wileECoyote, 1.M*EUR) } // wrong party
|
||||||
|
|
||||||
|
val outStateBad1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad1 )
|
||||||
|
val outStateBad2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad2 )
|
||||||
|
val outStateBad3 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad3 )
|
||||||
|
|
||||||
val inState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract)
|
val inState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract)
|
||||||
|
|
||||||
@ -33,6 +44,7 @@ class FXSwap {
|
|||||||
|
|
||||||
transaction {
|
transaction {
|
||||||
output { inState }
|
output { inState }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
this `fails with` "transaction has a single command"
|
this `fails with` "transaction has a single command"
|
||||||
|
|
||||||
@ -57,6 +69,26 @@ class FXSwap {
|
|||||||
input { inState }
|
input { inState }
|
||||||
output { outState1 }
|
output { outState1 }
|
||||||
output { outState2 }
|
output { outState2 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
|
this `fails with` "action must be defined"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
|
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `execute - reversed order`() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outState2 }
|
||||||
|
output { outState1 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
@ -75,6 +107,7 @@ class FXSwap {
|
|||||||
input { inState }
|
input { inState }
|
||||||
output { outState1 }
|
output { outState1 }
|
||||||
output { outState2 }
|
output { outState2 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") }
|
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
this `fails with` "action must be authorized"
|
this `fails with` "action must be authorized"
|
||||||
@ -82,13 +115,53 @@ class FXSwap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `execute - outState mismatch`() {
|
fun `execute - outState mismatch 1`() {
|
||||||
transaction {
|
transaction {
|
||||||
input { inState }
|
input { inState }
|
||||||
output { outState1 }
|
output { outState1 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
this `fails with` "output state must match action result state"
|
this `fails with` "output state must match action result state"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `execute - outState mismatch 2`() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outState1 }
|
||||||
|
output { outStateBad2 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
|
this `fails with` "output states must match action result state"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `execute - outState mismatch 3`() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outStateBad1 }
|
||||||
|
output { outState2 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
|
this `fails with` "output states must match action result state"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `execute - outState mismatch 4`() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outState1 }
|
||||||
|
output { outStateBad3 }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
|
this `fails with` "output states must match action result state"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
import com.r3corda.core.testing.DUMMY_NOTARY
|
import com.r3corda.core.testing.DUMMY_NOTARY
|
||||||
|
import com.r3corda.core.testing.TEST_TX_TIME
|
||||||
import com.r3corda.core.testing.transaction
|
import com.r3corda.core.testing.transaction
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ class ZeroCouponBond {
|
|||||||
transaction {
|
transaction {
|
||||||
input { inState }
|
input { inState }
|
||||||
output { outState }
|
output { outState }
|
||||||
|
timestamp(TEST_TX_TIME)
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
@ -82,6 +84,7 @@ class ZeroCouponBond {
|
|||||||
transaction {
|
transaction {
|
||||||
input { inState }
|
input { inState }
|
||||||
output { outState }
|
output { outState }
|
||||||
|
timestamp(TEST_TX_TIME)
|
||||||
|
|
||||||
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") }
|
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
this `fails with` "action must be authorized"
|
this `fails with` "action must be authorized"
|
||||||
@ -93,6 +96,7 @@ class ZeroCouponBond {
|
|||||||
transaction {
|
transaction {
|
||||||
input { inState }
|
input { inState }
|
||||||
output { outStateWrong }
|
output { outStateWrong }
|
||||||
|
timestamp(TEST_TX_TIME)
|
||||||
|
|
||||||
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") }
|
||||||
this `fails with` "output state must match action result state"
|
this `fails with` "output state must match action result state"
|
||||||
|
Loading…
Reference in New Issue
Block a user