Skip to content

Instantly share code, notes, and snippets.

@nimmaj
Created February 6, 2018 14:04
Show Gist options
  • Save nimmaj/b8b1c7c26fcd76ce110bafd72b3dd387 to your computer and use it in GitHub Desktop.
Save nimmaj/b8b1c7c26fcd76ce110bafd72b3dd387 to your computer and use it in GitHub Desktop.
Two unconsumed linear states with same UniqueIdentifier in Corda (2.0) FlowTest
package io.bluebank.daotest.v3.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.*
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode
import net.corda.testing.*
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After
import org.junit.Assert
import org.junit.Before
import org.junit.Test
class StateStateFlowTest {
lateinit var network: MockNetwork
lateinit var member1: StartedNode<MockNetwork.MockNode>
lateinit var member1Services: MockServices
lateinit var notaryServices: MockServices
lateinit var notary: Party
@Before
fun setup() {
setCordappPackages("io.bluebank.daotest.v3.flows")
member1Services = MockServices(MEGA_CORP_KEY)
notaryServices = MockServices(DUMMY_NOTARY_KEY)
network = MockNetwork()
val nodes = network.createSomeNodes(1)
member1 = nodes.partyNodes[0]
network.runNetwork()
notary = member1.services.getDefaultNotary()
}
@After
fun tearDown() {
network.stopNodes()
unsetCordappPackages()
}
@Test
fun `provoke flow`() {
val memberParty = member1.info.legalIdentities.first()
val tx1 = TestContract.generateNewState("firstString", memberParty, notary).let {
val ptx = member1Services.signInitialTransaction(it)
notaryServices.addSignature(ptx)
}
val tx2 = TestContract.generateMutate(tx1.tx.outRef(0), "secondString", notary).let {
val ptx = member1Services.signInitialTransaction(it)
notaryServices.addSignature(ptx)
}
member1.database.transaction {
member1.services.recordTransactions(tx1, tx2)
}
val future = member1.services.startFlow(TestFlow()).resultFuture
network.runNetwork()
future.getOrThrow()
}
}
@InitiatingFlow
class TestFlow: FlowLogic<Any>() {
@Suspendable
override fun call() {
// status = Vault.StateStatus.UNCONSUMED is implicit, I believe, and doesn't change the result
val vaultPage = serviceHub.vaultService.queryBy(TestState::class.java, QueryCriteria.LinearStateQueryCriteria(externalId = listOf("stateName")))
Assert.assertEquals("there should be 1 unconsumed state",1, vaultPage.states.size)
}
}
@CordaSerializable
data class TestState(val name: String, val someString: String, val owner: Party, override val linearId: UniqueIdentifier = UniqueIdentifier(name)): LinearState {
override val participants: List<AbstractParty>
get() = listOf(owner)
fun copyWith(newString: String): TestState {
return TestState(name, newString, owner, linearId)
}
}
val TEST_CONTRACT_ID = "io.bluebank.daotest.v3.flows.TestContract"
open class TestContract : Contract {
companion object {
fun generateNewState(someString: String, owner: Party, notary: Party): TransactionBuilder {
val newState = TestState("stateName", someString, owner)
val contractAndState = StateAndContract(newState, TEST_CONTRACT_ID)
val cmd = Command(Commands.Create(), listOf(owner.owningKey))
val txBuilder = TransactionBuilder(notary = notary)
txBuilder.withItems(contractAndState, cmd)
return txBuilder
}
fun generateMutate(oldState: StateAndRef<TestState>, newString: String, notary: Party): TransactionBuilder {
val newState = oldState.state.data.copyWith(newString)
val contractAndState = StateAndContract(newState, TEST_CONTRACT_ID)
val cmd = Command(Commands.Mutate(), listOf(newState.owner.owningKey))
val txBuilder = TransactionBuilder(notary = notary)
txBuilder.withItems(oldState, contractAndState, cmd)
return txBuilder
}
}
override fun verify(tx: LedgerTransaction) {
// it's just awesome
}
interface Commands : CommandData {
class Create : TypeOnlyCommandData(), Commands
class Mutate: TypeOnlyCommandData(), Commands
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment