Remove ClashingThreads exception by tightening up unique id on LinearState to be a secure random value, with constraints that it cannot be duplicated. Also, rename to linearId rather than the confusing thread.

Try providing a helper interface to encourage enforcing LinearState rules

Fixup after rebase

Change to using Clauses for verifying LinearState standard properties

Fix whitespace change

Tidy up ClauseVerifier after PR comments

Change from SecureHash to a TradeIdentifier class

Change TradeIdentifier to UniqueIdentifier
This commit is contained in:
Matthew Nesbit
2016-08-11 10:27:25 +01:00
parent 3f63aecf6c
commit 696b9741dd
11 changed files with 116 additions and 88 deletions

View File

@ -9,7 +9,7 @@ import com.r3corda.contracts.InterestRateSwap
import com.r3corda.core.RunOnCallerThread
import com.r3corda.core.contracts.SignedTransaction
import com.r3corda.core.contracts.StateAndRef
import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.contracts.UniqueIdentifier
import com.r3corda.core.failure
import com.r3corda.core.node.services.linearHeadsOfType
import com.r3corda.core.node.services.testing.MockIdentityService
@ -80,7 +80,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val node1: SimulatedNode = banks[i]
val node2: SimulatedNode = banks[j]
val swaps: Map<SecureHash, StateAndRef<InterestRateSwap.State>> = node1.services.walletService.linearHeadsOfType<InterestRateSwap.State>()
val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> = node1.services.walletService.linearHeadsOfType<InterestRateSwap.State>()
val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.values.single()
// Do we have any more days left in this deal's lifetime? If not, return.

View File

@ -82,7 +82,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
override val participants: List<PublicKey>
get() = throw UnsupportedOperationException()
override val thread = SecureHash.sha256("does not matter but we need it to be unique ${Math.random()}")
override val linearId = UniqueIdentifier()
override fun isRelevant(ourKeys: Set<PublicKey>): Boolean = true

View File

@ -104,56 +104,50 @@ class WalletWithCashTest {
@Test
fun branchingLinearStatesFails() {
fun branchingLinearStatesFailsToVerify() {
val freshKey = services.keyManagementService.freshKey()
val thread = SecureHash.sha256("thread")
val linearId = UniqueIdentifier()
// Issue a linear state
val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearState(thread = thread, participants = listOf(freshKey.public)))
signWith(freshKey)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
wallet.notify(dummyIssue.tx)
assertEquals(1, wallet.currentWallet.states.toList().size)
// Issue another linear state of the same thread (nonce different)
val dummyIssue2 = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearState(thread = thread, participants = listOf(freshKey.public)))
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public)))
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public)))
signWith(freshKey)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
assertThatThrownBy {
wallet.notify(dummyIssue2.tx)
dummyIssue.toLedgerTransaction(services).verify()
}
assertEquals(1, wallet.currentWallet.states.toList().size)
}
@Test
fun sequencingLinearStatesWorks() {
val freshKey = services.keyManagementService.freshKey()
val thread = SecureHash.sha256("thread")
val linearId = UniqueIdentifier()
// Issue a linear state
val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearState(thread = thread, participants = listOf(freshKey.public)))
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public)))
signWith(freshKey)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
dummyIssue.toLedgerTransaction(services).verify()
wallet.notify(dummyIssue.tx)
assertEquals(1, wallet.currentWallet.states.toList().size)
// Move the same state
val dummyMove = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearState(thread = thread, participants = listOf(freshKey.public)))
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public)))
addInputState(dummyIssue.tx.outRef<LinearState>(0))
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
dummyIssue.toLedgerTransaction(services).verify()
wallet.notify(dummyMove.tx)
assertEquals(1, wallet.currentWallet.states.toList().size)
}