mirror of
https://github.com/corda/corda.git
synced 2024-12-19 13:08:04 +00:00
CORDA-1266 When a cash output is identical only the fist output is saved. (#3244)
This commit is contained in:
parent
1c1b492532
commit
0a4d98161a
@ -131,9 +131,10 @@ class NodeVaultService(
|
|||||||
fun makeUpdate(tx: WireTransaction): Vault.Update<ContractState>? {
|
fun makeUpdate(tx: WireTransaction): Vault.Update<ContractState>? {
|
||||||
val ourNewStates = when (statesToRecord) {
|
val ourNewStates = when (statesToRecord) {
|
||||||
StatesToRecord.NONE -> throw AssertionError("Should not reach here")
|
StatesToRecord.NONE -> throw AssertionError("Should not reach here")
|
||||||
StatesToRecord.ONLY_RELEVANT -> tx.outputs.filter { isRelevant(it.data, keyManagementService.filterMyKeys(tx.outputs.flatMap { it.data.participants.map { it.owningKey } }).toSet()) }
|
StatesToRecord.ONLY_RELEVANT -> tx.outputs.withIndex().filter {
|
||||||
StatesToRecord.ALL_VISIBLE -> tx.outputs
|
isRelevant(it.value.data, keyManagementService.filterMyKeys(tx.outputs.flatMap { it.data.participants.map { it.owningKey } }).toSet()) }
|
||||||
}.map { tx.outRef<ContractState>(it.data) }
|
StatesToRecord.ALL_VISIBLE -> tx.outputs.withIndex()
|
||||||
|
}.map { tx.outRef<ContractState>(it.index) }
|
||||||
|
|
||||||
// Retrieve all unconsumed states for this transaction's inputs
|
// Retrieve all unconsumed states for this transaction's inputs
|
||||||
val consumedStates = loadStates(tx.inputs)
|
val consumedStates = loadStates(tx.inputs)
|
||||||
|
@ -4,10 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import com.nhaarman.mockito_kotlin.argThat
|
import com.nhaarman.mockito_kotlin.argThat
|
||||||
import com.nhaarman.mockito_kotlin.doNothing
|
import com.nhaarman.mockito_kotlin.doNothing
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.contracts.Issued
|
|
||||||
import net.corda.core.contracts.StateAndRef
|
|
||||||
import net.corda.core.contracts.StateRef
|
|
||||||
import net.corda.core.crypto.NullKeys
|
import net.corda.core.crypto.NullKeys
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.identity.*
|
import net.corda.core.identity.*
|
||||||
@ -687,4 +684,50 @@ class NodeVaultServiceTest {
|
|||||||
}
|
}
|
||||||
assertEquals(currentCashStates + 1, countCash())
|
assertEquals(currentCashStates + 1, countCash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `insert equal cash states issued by single transaction`() {
|
||||||
|
val nodeIdentity = MEGA_CORP
|
||||||
|
val coins = listOf(1.DOLLARS, 1.DOLLARS).map { it.issuedBy(nodeIdentity.ref(1)) }
|
||||||
|
|
||||||
|
//create single transaction with 2 'identical' cash outputs
|
||||||
|
val txb = TransactionBuilder(DUMMY_NOTARY)
|
||||||
|
coins.map { txb.addOutputState(TransactionState(Cash.State(it, nodeIdentity), Cash.PROGRAM_ID, DUMMY_NOTARY)) }
|
||||||
|
txb.addCommand(Cash.Commands.Issue(), nodeIdentity.owningKey)
|
||||||
|
val issueTx = txb.toWireTransaction(services)
|
||||||
|
|
||||||
|
// ensure transaction contract state is persisted in DBStorage
|
||||||
|
val signedIssuedTx = services.signInitialTransaction(txb)
|
||||||
|
(services.validatedTransactions as WritableTransactionStorage).addTransaction(signedIssuedTx)
|
||||||
|
|
||||||
|
database.transaction { vaultService.notify(StatesToRecord.ONLY_RELEVANT, issueTx) }
|
||||||
|
|
||||||
|
val recordedStates = database.transaction {
|
||||||
|
vaultService.queryBy<Cash.State>().states.size
|
||||||
|
}
|
||||||
|
assertThat(recordedStates).isEqualTo(coins.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `insert different cash states issued by single transaction`() {
|
||||||
|
val nodeIdentity = MEGA_CORP
|
||||||
|
val coins = listOf(2.DOLLARS, 1.DOLLARS).map { it.issuedBy(nodeIdentity.ref(1)) }
|
||||||
|
|
||||||
|
//create single transaction with 2 'identical' cash outputs
|
||||||
|
val txb = TransactionBuilder(DUMMY_NOTARY)
|
||||||
|
coins.map { txb.addOutputState(TransactionState(Cash.State(it, nodeIdentity), Cash.PROGRAM_ID, DUMMY_NOTARY)) }
|
||||||
|
txb.addCommand(Cash.Commands.Issue(), nodeIdentity.owningKey)
|
||||||
|
val issueTx = txb.toWireTransaction(services)
|
||||||
|
|
||||||
|
// ensure transaction contract state is persisted in DBStorage
|
||||||
|
val signedIssuedTx = services.signInitialTransaction(txb)
|
||||||
|
(services.validatedTransactions as WritableTransactionStorage).addTransaction(signedIssuedTx)
|
||||||
|
|
||||||
|
database.transaction { vaultService.notify(StatesToRecord.ONLY_RELEVANT, issueTx) }
|
||||||
|
|
||||||
|
val recordedStates = database.transaction {
|
||||||
|
vaultService.queryBy<Cash.State>().states.size
|
||||||
|
}
|
||||||
|
assertThat(recordedStates).isEqualTo(coins.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user