Ensure transactions in tests have commands (#1200)

* Ensure transactions in tests have commands
This commit is contained in:
Andrius Dagys 2017-08-16 10:06:46 +01:00 committed by GitHub
parent 435dcf6af4
commit 1e0a26e8e5
15 changed files with 135 additions and 63 deletions

View File

@ -7,6 +7,7 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.TestDependencyInjectionBase import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -50,7 +51,11 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
private fun makeDummyStateAndRef(data: Any): StateAndRef<*> { private fun makeDummyStateAndRef(data: Any): StateAndRef<*> {
val dummyState = makeDummyState(data) val dummyState = makeDummyState(data)
val fakeIssueTx = services.signInitialTransaction(TransactionBuilder(notary = DUMMY_NOTARY).addOutputState(dummyState)) val fakeIssueTx = services.signInitialTransaction(
TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(dummyState)
.addCommand(dummyCommand())
)
services.recordTransactions(fakeIssueTx) services.recordTransactions(fakeIssueTx)
val dummyStateRef = StateRef(fakeIssueTx.id, 0) val dummyStateRef = StateRef(fakeIssueTx.id, 0)
return StateAndRef(TransactionState(dummyState, DUMMY_NOTARY, null), dummyStateRef) return StateAndRef(TransactionState(dummyState, DUMMY_NOTARY, null), dummyStateRef)

View File

@ -34,14 +34,15 @@ class TransactionGraphSearchTests : TestDependencyInjectionBase() {
val notaryServices = MockServices(DUMMY_NOTARY_KEY) val notaryServices = MockServices(DUMMY_NOTARY_KEY)
val originBuilder = TransactionBuilder(DUMMY_NOTARY) val originBuilder = TransactionBuilder(DUMMY_NOTARY)
originBuilder.addOutputState(DummyState(random31BitValue())) .addOutputState(DummyState(random31BitValue()))
originBuilder.addCommand(command, MEGA_CORP_PUBKEY) .addCommand(command, MEGA_CORP_PUBKEY)
val originPtx = megaCorpServices.signInitialTransaction(originBuilder) val originPtx = megaCorpServices.signInitialTransaction(originBuilder)
val originTx = notaryServices.addSignature(originPtx) val originTx = notaryServices.addSignature(originPtx)
val inputBuilder = TransactionBuilder(DUMMY_NOTARY) val inputBuilder = TransactionBuilder(DUMMY_NOTARY)
inputBuilder.addInputState(originTx.tx.outRef<DummyState>(0)) .addInputState(originTx.tx.outRef<DummyState>(0))
.addCommand(dummyCommand(MEGA_CORP_PUBKEY))
val inputPtx = megaCorpServices.signInitialTransaction(inputBuilder) val inputPtx = megaCorpServices.signInitialTransaction(inputBuilder)
val inputTx = megaCorpServices.addSignature(inputPtx) val inputTx = megaCorpServices.addSignature(inputPtx)

View File

@ -488,7 +488,8 @@ class Obligation<P : Any> : Contract {
*/ */
fun generateCloseOutNetting(tx: TransactionBuilder, fun generateCloseOutNetting(tx: TransactionBuilder,
signer: AbstractParty, signer: AbstractParty,
vararg states: State<P>) { vararg inputs: StateAndRef<State<P>>) {
val states = inputs.map { it.state.data }
val netState = states.firstOrNull()?.bilateralNetState val netState = states.firstOrNull()?.bilateralNetState
requireThat { requireThat {
@ -498,6 +499,7 @@ class Obligation<P : Any> : Contract {
"signer is in the state parties" using (signer in netState!!.partyKeys) "signer is in the state parties" using (signer in netState!!.partyKeys)
} }
tx.withItems(*inputs)
val out = states.reduce(State<P>::net) val out = states.reduce(State<P>::net)
if (out.quantity > 0L) if (out.quantity > 0L)
tx.addOutputState(out) tx.addOutputState(out)
@ -567,10 +569,14 @@ class Obligation<P : Any> : Contract {
fun generatePaymentNetting(tx: TransactionBuilder, fun generatePaymentNetting(tx: TransactionBuilder,
issued: Issued<Obligation.Terms<P>>, issued: Issued<Obligation.Terms<P>>,
notary: Party, notary: Party,
vararg states: State<P>) { vararg inputs: StateAndRef<State<P>>) {
val states = inputs.map { it.state.data }
requireThat { requireThat {
"all states are in the normal lifecycle state " using (states.all { it.lifecycle == Lifecycle.NORMAL }) "all states are in the normal lifecycle state " using (states.all { it.lifecycle == Lifecycle.NORMAL })
} }
tx.withItems(*inputs)
val groups = states.groupBy { it.multilateralNetState } val groups = states.groupBy { it.multilateralNetState }
val partyLookup = HashMap<PublicKey, AbstractParty>() val partyLookup = HashMap<PublicKey, AbstractParty>()
val signers = states.map { it.beneficiary }.union(states.map { it.obligor }).toSet() val signers = states.map { it.beneficiary }.union(states.map { it.obligor }).toSet()

View File

@ -69,15 +69,16 @@ class ObligationTests {
fun trivial() { fun trivial() {
transaction { transaction {
input { inState } input { inState }
this `fails with` "the amounts balance"
tweak { tweak {
output { outState.copy(quantity = 2000.DOLLARS.quantity) } output { outState.copy(quantity = 2000.DOLLARS.quantity) }
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }
tweak { tweak {
output { outState } output { outState }
// No command arguments command(CHARLIE.owningKey) { DummyCommandData }
// Invalid command
this `fails with` "required net.corda.contracts.asset.Obligation.Commands.Move command" this `fails with` "required net.corda.contracts.asset.Obligation.Commands.Move command"
} }
tweak { tweak {
@ -225,8 +226,8 @@ class ObligationTests {
@Test @Test
fun `generate close-out net transaction`() { fun `generate close-out net transaction`() {
initialiseTestSerialization() initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE))
val tx = TransactionBuilder(DUMMY_NOTARY).apply { val tx = TransactionBuilder(DUMMY_NOTARY).apply {
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice) Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction() }.toWireTransaction()
@ -237,8 +238,8 @@ class ObligationTests {
@Test @Test
fun `generate close-out net transaction with remainder`() { fun `generate close-out net transaction with remainder`() {
initialiseTestSerialization() initialiseTestSerialization()
val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB) val obligationAliceToBob = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB))
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE))
val tx = TransactionBuilder(DUMMY_NOTARY).apply { val tx = TransactionBuilder(DUMMY_NOTARY).apply {
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice) Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction() }.toWireTransaction()
@ -252,10 +253,10 @@ class ObligationTests {
@Test @Test
fun `generate payment net transaction`() { fun `generate payment net transaction`() {
initialiseTestSerialization() initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE))
val tx = TransactionBuilder(DUMMY_NOTARY).apply { val tx = TransactionBuilder(DUMMY_NOTARY).apply {
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice) Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.state.data.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction() }.toWireTransaction()
assertEquals(0, tx.outputs.size) assertEquals(0, tx.outputs.size)
} }
@ -264,17 +265,25 @@ class ObligationTests {
@Test @Test
fun `generate payment net transaction with remainder`() { fun `generate payment net transaction with remainder`() {
initialiseTestSerialization() initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE) val obligationAliceToBobState = obligationAliceToBob.state.data
val tx = TransactionBuilder(null).apply { val obligationBobToAlice = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE))
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice) val obligationBobToAliceState = obligationBobToAlice.state.data
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBobState.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction() }.toWireTransaction()
assertEquals(1, tx.outputs.size) assertEquals(1, tx.outputs.size)
val expected = obligationBobToAlice.copy(quantity = obligationBobToAlice.quantity - obligationAliceToBob.quantity) val expected = obligationBobToAliceState.copy(quantity = obligationBobToAliceState.quantity - obligationAliceToBobState.quantity)
val actual = tx.getOutput(0) val actual = tx.getOutput(0)
assertEquals(expected, actual) assertEquals(expected, actual)
} }
private inline fun <reified T: ContractState> getStateAndRef(state: T): StateAndRef<T> {
val txState = TransactionState(state, DUMMY_NOTARY)
return StateAndRef(txState, StateRef(SecureHash.randomSHA256(), 0))
}
/** Test generating a transaction to mark outputs as having defaulted. */ /** Test generating a transaction to mark outputs as having defaulted. */
@Test @Test
fun `generate set lifecycle`() { fun `generate set lifecycle`() {
@ -597,17 +606,22 @@ class ObligationTests {
@Test @Test
fun zeroSizedValues() { fun zeroSizedValues() {
transaction { transaction {
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
tweak {
input { inState } input { inState }
input { inState.copy(quantity = 0L) } input { inState.copy(quantity = 0L) }
this `fails with` "zero sized inputs" this `fails with` "zero sized inputs"
} }
transaction { tweak {
input { inState } input { inState }
output { inState } output { inState }
output { inState.copy(quantity = 0L) } output { inState.copy(quantity = 0L) }
this `fails with` "zero sized outputs" this `fails with` "zero sized outputs"
} }
} }
}
@Test @Test
fun trivialMismatches() { fun trivialMismatches() {
@ -615,6 +629,7 @@ class ObligationTests {
transaction { transaction {
input { inState } input { inState }
output { outState `issued by` MINI_CORP } output { outState `issued by` MINI_CORP }
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }
// Can't mix currencies. // Can't mix currencies.
@ -622,6 +637,7 @@ class ObligationTests {
input { inState } input { inState }
output { outState.copy(quantity = 80000, template = megaCorpDollarSettlement) } output { outState.copy(quantity = 80000, template = megaCorpDollarSettlement) }
output { outState.copy(quantity = 20000, template = megaCorpPoundSettlement) } output { outState.copy(quantity = 20000, template = megaCorpPoundSettlement) }
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }
transaction { transaction {
@ -634,6 +650,7 @@ class ObligationTests {
) )
} }
output { outState.copy(quantity = 115000) } output { outState.copy(quantity = 115000) }
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }
// Can't have superfluous input states from different issuers. // Can't have superfluous input states from different issuers.
@ -704,12 +721,14 @@ class ObligationTests {
// Can't merge them together. // Can't merge them together.
tweak { tweak {
output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L) } output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L) }
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }
// Missing MiniCorp deposit // Missing MiniCorp deposit
tweak { tweak {
output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) } output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) } output { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
this `fails with` "the amounts balance" this `fails with` "the amounts balance"
} }

View File

@ -15,6 +15,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.getTestPartyAndCertificate import net.corda.testing.getTestPartyAndCertificate
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.assertj.core.api.Assertions.assertThatExceptionOfType
@ -168,7 +169,7 @@ fun issueState(node: AbstractNode, notaryNode: AbstractNode): StateAndRef<*> {
fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode, notaryNode: AbstractNode): StateAndRef<DummyContract.MultiOwnerState> { fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode, notaryNode: AbstractNode): StateAndRef<DummyContract.MultiOwnerState> {
val state = TransactionState(DummyContract.MultiOwnerState(0, val state = TransactionState(DummyContract.MultiOwnerState(0,
listOf(nodeA.info.legalIdentity, nodeB.info.legalIdentity)), notaryNode.info.notaryIdentity) listOf(nodeA.info.legalIdentity, nodeB.info.legalIdentity)), notaryNode.info.notaryIdentity)
val tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state) val tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state, dummyCommand())
val signedByA = nodeA.services.signInitialTransaction(tx) val signedByA = nodeA.services.signInitialTransaction(tx)
val signedByAB = nodeB.services.addSignature(signedByA) val signedByAB = nodeB.services.addSignature(signedByA)
val stx = notaryNode.services.addSignature(signedByAB, notaryNode.services.notaryIdentityKey) val stx = notaryNode.services.addSignature(signedByAB, notaryNode.services.notaryIdentityKey)

View File

@ -19,6 +19,7 @@ import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import net.corda.testing.node.makeTestDatabaseProperties import net.corda.testing.node.makeTestDatabaseProperties
import net.corda.testing.node.makeTestIdentityService import net.corda.testing.node.makeTestIdentityService
@ -204,7 +205,7 @@ class RequeryConfigurationTest : TestDependencyInjectionBase() {
inputs = listOf(StateRef(SecureHash.randomSHA256(), index)), inputs = listOf(StateRef(SecureHash.randomSHA256(), index)),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
commands = emptyList(), commands = listOf(dummyCommand()),
notary = DUMMY_NOTARY, notary = DUMMY_NOTARY,
timeWindow = null timeWindow = null
) )

View File

@ -22,6 +22,7 @@ import net.corda.node.services.statemachine.StateMachineManager
import net.corda.node.services.transactions.ValidatingNotaryService import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
@ -71,7 +72,8 @@ class ScheduledFlowTests {
val notary = serviceHub.networkMapCache.getAnyNotary() val notary = serviceHub.networkMapCache.getAnyNotary()
val builder = TransactionBuilder(notary) val builder = TransactionBuilder(notary)
builder.withItems(scheduledState) .addOutputState(scheduledState)
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
val tx = serviceHub.signInitialTransaction(builder) val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity))) subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
} }
@ -91,7 +93,9 @@ class ScheduledFlowTests {
val notary = state.state.notary val notary = state.state.notary
val newStateOutput = scheduledState.copy(processed = true) val newStateOutput = scheduledState.copy(processed = true)
val builder = TransactionBuilder(notary) val builder = TransactionBuilder(notary)
builder.withItems(state, newStateOutput) .addInputState(state)
.addOutputState(newStateOutput)
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
val tx = serviceHub.signInitialTransaction(builder) val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination))) subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
} }

View File

@ -4,8 +4,8 @@ import net.corda.core.contracts.StateRef
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
import net.corda.core.node.services.VaultService
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.node.services.VaultService
import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.MappedSchema
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
@ -220,7 +220,7 @@ class DBTransactionStorageTests : TestDependencyInjectionBase() {
inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)), inputs = listOf(StateRef(SecureHash.randomSHA256(), 0)),
attachments = emptyList(), attachments = emptyList(),
outputs = emptyList(), outputs = emptyList(),
commands = emptyList(), commands = listOf(dummyCommand()),
notary = DUMMY_NOTARY, notary = DUMMY_NOTARY,
timeWindow = null timeWindow = null
) )

View File

@ -593,7 +593,8 @@ class FlowFrameworkTests {
@Test @Test
fun `wait for transaction`() { fun `wait for transaction`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity) val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
ptx.addOutputState(DummyState()) .addOutputState(DummyState())
.addCommand(dummyCommand(node1.services.legalIdentityKey))
val stx = node1.services.signInitialTransaction(ptx) val stx = node1.services.signInitialTransaction(ptx)
val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) { val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) {
@ -607,7 +608,8 @@ class FlowFrameworkTests {
@Test @Test
fun `committer throws exception before calling the finality flow`() { fun `committer throws exception before calling the finality flow`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity) val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
ptx.addOutputState(DummyState()) .addOutputState(DummyState())
.addCommand(dummyCommand())
val stx = node1.services.signInitialTransaction(ptx) val stx = node1.services.signInitialTransaction(ptx)
node1.registerFlowFactory(WaitingFlows.Waiter::class) { node1.registerFlowFactory(WaitingFlows.Waiter::class) {
@ -623,7 +625,8 @@ class FlowFrameworkTests {
@Test @Test
fun `verify vault query service is tokenizable by force checkpointing within a flow`() { fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity) val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
ptx.addOutputState(DummyState()) .addOutputState(DummyState())
.addCommand(dummyCommand(node1.services.legalIdentityKey))
val stx = node1.services.signInitialTransaction(ptx) val stx = node1.services.signInitialTransaction(ptx)
node1.registerFlowFactory(VaultQueryFlow::class) { node1.registerFlowFactory(VaultQueryFlow::class) {

View File

@ -16,6 +16,7 @@ import net.corda.node.internal.AbstractNode
import net.corda.node.services.network.NetworkMapService import net.corda.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -50,8 +51,10 @@ class NotaryServiceTests {
fun `should sign a unique transaction with a valid time-window`() { fun `should sign a unique transaction with a valid time-window`() {
val stx = run { val stx = run {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
tx.setTimeWindow(Instant.now(), 30.seconds) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.setTimeWindow(Instant.now(), 30.seconds)
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -64,7 +67,9 @@ class NotaryServiceTests {
fun `should sign a unique transaction without a time-window`() { fun `should sign a unique transaction without a time-window`() {
val stx = run { val stx = run {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -77,8 +82,10 @@ class NotaryServiceTests {
fun `should report error for transaction with an invalid time-window`() { fun `should report error for transaction with an invalid time-window`() {
val stx = run { val stx = run {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
tx.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -92,7 +99,9 @@ class NotaryServiceTests {
fun `should sign identical transaction multiple times (signing is idempotent)`() { fun `should sign identical transaction multiple times (signing is idempotent)`() {
val stx = run { val stx = run {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -110,12 +119,16 @@ class NotaryServiceTests {
fun `should report conflict when inputs are reused across transactions`() { fun `should report conflict when inputs are reused across transactions`() {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val stx = run { val stx = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
val stx2 = run { val stx2 = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
tx.addInputState(issueState(clientNode)) .addInputState(inputState)
.addInputState(issueState(clientNode))
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }

View File

@ -18,6 +18,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MEGA_CORP_KEY
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -52,7 +53,9 @@ class ValidatingNotaryServiceTests {
fun `should report error for invalid transaction dependency`() { fun `should report error for invalid transaction dependency`() {
val stx = run { val stx = run {
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity) val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }

View File

@ -222,6 +222,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply { val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
addCommand(dummyCommand(notaryServices.legalIdentityKey))
} }
val dummyIssue = notaryServices.signInitialTransaction(dummyIssueBuilder) val dummyIssue = notaryServices.signInitialTransaction(dummyIssueBuilder)
@ -241,7 +242,8 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
// Issue a linear state // Issue a linear state
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY) val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
dummyIssueBuilder.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) .addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
.addCommand(dummyCommand(notaryServices.legalIdentityKey))
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder) val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
val dummyIssue = services.addSignature(dummyIssuePtx) val dummyIssue = services.addSignature(dummyIssuePtx)
@ -251,10 +253,10 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
assertThat(vaultQuery.queryBy<DummyLinearContract.State>().states).hasSize(1) assertThat(vaultQuery.queryBy<DummyLinearContract.State>().states).hasSize(1)
// Move the same state // Move the same state
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply { val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) .addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
addInputState(dummyIssue.tx.outRef<LinearState>(0)) .addInputState(dummyIssue.tx.outRef<LinearState>(0))
} .addCommand(dummyCommand(notaryServices.legalIdentityKey))
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder) val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)
@ -318,6 +320,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity))) addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)))
addInputState(linearStates.first()) addInputState(linearStates.first())
addInputState(deals.first()) addInputState(deals.first())
addCommand(dummyCommand(notaryServices.legalIdentityKey))
} }
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder) val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)

View File

@ -123,7 +123,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Test @Test
fun `refuse to sign with no relevant commands`() { fun `refuse to sign with no relevant commands`() {
database.transaction { database.transaction {
val tx = makeTX() val tx = makeFullTx()
val wtx1 = tx.toWireTransaction() val wtx1 = tx.toWireTransaction()
fun filterAllOutputs(elem: Any): Boolean { fun filterAllOutputs(elem: Any): Boolean {
return when (elem) { return when (elem) {
@ -145,7 +145,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Test @Test
fun `sign successfully`() { fun `sign successfully`() {
database.transaction { database.transaction {
val tx = makeTX() val tx = makePartialTX()
val fix = oracle.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M"))).first() val fix = oracle.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M"))).first()
tx.addCommand(fix, oracle.identity.owningKey) tx.addCommand(fix, oracle.identity.owningKey)
// Sign successfully. // Sign successfully.
@ -159,7 +159,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Test @Test
fun `do not sign with unknown fix`() { fun `do not sign with unknown fix`() {
database.transaction { database.transaction {
val tx = makeTX() val tx = makePartialTX()
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val badFix = Fix(fixOf, BigDecimal("0.6789")) val badFix = Fix(fixOf, BigDecimal("0.6789"))
tx.addCommand(badFix, oracle.identity.owningKey) tx.addCommand(badFix, oracle.identity.owningKey)
@ -173,7 +173,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Test @Test
fun `do not sign too many leaves`() { fun `do not sign too many leaves`() {
database.transaction { database.transaction {
val tx = makeTX() val tx = makePartialTX()
val fix = oracle.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M"))).first() val fix = oracle.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M"))).first()
fun filtering(elem: Any): Boolean { fun filtering(elem: Any): Boolean {
return when (elem) { return when (elem) {
@ -191,7 +191,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
@Test @Test
fun `empty partial transaction to sign`() { fun `empty partial transaction to sign`() {
val tx = makeTX() val tx = makeFullTx()
val wtx = tx.toWireTransaction() val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction(Predicate { false }) val ftx = wtx.buildFilteredTransaction(Predicate { false })
assertFailsWith<MerkleTreeException> { oracle.sign(ftx) } assertFailsWith<MerkleTreeException> { oracle.sign(ftx) }
@ -207,7 +207,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
n2.database.transaction { n2.database.transaction {
n2.installCordaService(NodeInterestRates.Oracle::class.java).knownFixes = TEST_DATA n2.installCordaService(NodeInterestRates.Oracle::class.java).knownFixes = TEST_DATA
} }
val tx = TransactionBuilder(null) val tx = makePartialTX()
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first() val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1")) val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1"))
@ -238,6 +238,8 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
} }
} }
private fun makeTX() = TransactionBuilder(DUMMY_NOTARY).withItems( private fun makePartialTX() = TransactionBuilder(DUMMY_NOTARY).withItems(
1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE `with notary` DUMMY_NOTARY) 1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE `with notary` DUMMY_NOTARY)
private fun makeFullTx() = makePartialTX().withItems(dummyCommand())
} }

View File

@ -74,7 +74,9 @@ val DUMMY_CA: CertificateAndKeyPair by lazy {
CertificateAndKeyPair(cert, DUMMY_CA_KEY) CertificateAndKeyPair(cert, DUMMY_CA_KEY)
} }
fun dummyCommand(vararg signers: PublicKey) = Command<TypeOnlyCommandData>(object : TypeOnlyCommandData() {}, signers.toList()) fun dummyCommand(vararg signers: PublicKey = arrayOf(generateKeyPair().public) ) = Command<TypeOnlyCommandData>(DummyCommandData, signers.toList())
object DummyCommandData : TypeOnlyCommandData()
val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY) val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY)
val DUMMY_PARTY: Party get() = Party(X500Name("CN=Dummy,O=Dummy,L=Madrid,C=ES"), DUMMY_KEY_1.public) val DUMMY_PARTY: Party get() = Party(X500Name("CN=Dummy,O=Dummy,L=Madrid,C=ES"), DUMMY_KEY_1.public)

View File

@ -4,11 +4,13 @@ package net.corda.testing.contracts
import net.corda.contracts.Commodity import net.corda.contracts.Commodity
import net.corda.contracts.DealState import net.corda.contracts.DealState
import net.corda.contracts.asset.* import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.CommodityContract
import net.corda.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.contracts.asset.DUMMY_OBLIGATION_ISSUER
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
import net.corda.core.utilities.getOrThrow
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
@ -18,9 +20,11 @@ import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.testing.CHARLIE import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY import net.corda.testing.DUMMY_NOTARY_KEY
import net.corda.testing.dummyCommand
import java.security.PublicKey import java.security.PublicKey
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
@ -38,6 +42,7 @@ fun ServiceHub.fillWithSomeTestDeals(dealIds: List<String>,
// Issue a deal state // Issue a deal state
val dummyIssue = TransactionBuilder(notary = notary).apply { val dummyIssue = TransactionBuilder(notary = notary).apply {
addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me))) addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me)))
addCommand(dummyCommand())
} }
val stx = signInitialTransaction(dummyIssue) val stx = signInitialTransaction(dummyIssue)
return@map addSignature(stx, notary.owningKey) return@map addSignature(stx, notary.owningKey)
@ -76,6 +81,7 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
linearNumber = linearNumber, linearNumber = linearNumber,
linearBoolean = linearBoolean, linearBoolean = linearBoolean,
linearTimestamp = linearTimestamp)) linearTimestamp = linearTimestamp))
addCommand(dummyCommand())
} }
return@map signInitialTransaction(dummyIssue).withAdditionalSignature(issuerKey, signatureMetadata) return@map signInitialTransaction(dummyIssue).withAdditionalSignature(issuerKey, signatureMetadata)
@ -194,6 +200,7 @@ fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>, notary: P
states.forEach { states.forEach {
val builder = TransactionBuilder(notary = notary).apply { val builder = TransactionBuilder(notary = notary).apply {
addInputState(it) addInputState(it)
addCommand(dummyCommand(notary.owningKey))
} }
val consumedTx = signInitialTransaction(builder, notary.owningKey) val consumedTx = signInitialTransaction(builder, notary.owningKey)
@ -205,6 +212,7 @@ fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>,
// Create a txn consuming different contract types // Create a txn consuming different contract types
var builder = TransactionBuilder(notary = notary).apply { var builder = TransactionBuilder(notary = notary).apply {
addInputState(stateAndRef) addInputState(stateAndRef)
addCommand(dummyCommand(notary.owningKey))
} }
val consumedTx = signInitialTransaction(builder, notary.owningKey) val consumedTx = signInitialTransaction(builder, notary.owningKey)
@ -214,6 +222,7 @@ fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>,
builder = TransactionBuilder(notary = notary).apply { builder = TransactionBuilder(notary = notary).apply {
addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId, addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId,
participants = stateAndRef.state.data.participants)) participants = stateAndRef.state.data.participants))
addCommand(dummyCommand(notary.owningKey))
} }
val producedTx = signInitialTransaction(builder, notary.owningKey) val producedTx = signInitialTransaction(builder, notary.owningKey)