mirror of
https://github.com/corda/corda.git
synced 2025-03-11 06:54:04 +00:00
CORDA-2665: Updated OwnableState relevancy check put back to V3 version (#4819)
* CORDA-2665: Updated OwnableState relevancy check is now gated on target version 4 https://github.com/corda/corda/pull/3789 changed the relevancy check of OwnableState to include the participants list in addition to the owner. This however breaks existing apps which assume (in their vault query) an OwnableState is recorded to the vault if-and-only-if the owner matches. * CORDA-2665 Don't switch to new behaviour on target version upgrade.
This commit is contained in:
parent
2ff7860e4b
commit
f52d158f2d
@ -20,11 +20,7 @@ import net.corda.node.services.api.SchemaService
|
||||
import net.corda.node.services.api.VaultServiceInternal
|
||||
import net.corda.node.services.schema.PersistentStateService
|
||||
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.bufferUntilDatabaseCommit
|
||||
import net.corda.nodeapi.internal.persistence.currentDBSession
|
||||
import net.corda.nodeapi.internal.persistence.wrapWithDatabaseTransaction
|
||||
import net.corda.nodeapi.internal.persistence.contextTransactionOrNull
|
||||
import net.corda.nodeapi.internal.persistence.*
|
||||
import org.hibernate.Session
|
||||
import rx.Observable
|
||||
import rx.subjects.PublishSubject
|
||||
@ -71,9 +67,7 @@ class NodeVaultService(
|
||||
*/
|
||||
fun isRelevant(state: ContractState, myKeys: Set<PublicKey>): Boolean {
|
||||
val keysToCheck = when (state) {
|
||||
// Sometimes developers forget to add the owning key to participants for OwnableStates.
|
||||
// TODO: This logic should probably be moved to OwnableState so we can just do a simple intersection here.
|
||||
is OwnableState -> (state.participants.map { it.owningKey } + state.owner.owningKey).toSet()
|
||||
is OwnableState -> listOf(state.owner.owningKey)
|
||||
else -> state.participants.map { it.owningKey }
|
||||
}
|
||||
return keysToCheck.any { it.containsAny(myKeys) }
|
||||
|
@ -22,8 +22,8 @@ import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.toNonEmptySet
|
||||
import net.corda.finance.*
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.finance.contracts.utils.sumCash
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.finance.workflows.asset.CashUtils
|
||||
import net.corda.finance.workflows.getCashBalance
|
||||
import net.corda.node.services.api.IdentityServiceInternal
|
||||
@ -42,6 +42,7 @@ import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.junit.*
|
||||
import rx.observers.TestSubscriber
|
||||
import java.math.BigDecimal
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.Executors
|
||||
@ -98,8 +99,8 @@ class NodeVaultServiceTest {
|
||||
vaultFiller = VaultFiller(services, dummyNotary)
|
||||
// This is safe because MockServices only ever have a single identity
|
||||
identity = services.myInfo.singleIdentityAndCert()
|
||||
issuerServices = MockServices(cordappPackages, dummyCashIssuer, mock<IdentityService>(), parameters)
|
||||
bocServices = MockServices(cordappPackages, bankOfCorda, mock<IdentityService>(), parameters)
|
||||
issuerServices = MockServices(cordappPackages, dummyCashIssuer, mock(), parameters)
|
||||
bocServices = MockServices(cordappPackages, bankOfCorda, mock(), parameters)
|
||||
services.identityService.verifyAndRegisterIdentity(DUMMY_CASH_ISSUER_IDENTITY)
|
||||
services.identityService.verifyAndRegisterIdentity(BOC_IDENTITY)
|
||||
}
|
||||
@ -129,6 +130,7 @@ class NodeVaultServiceTest {
|
||||
}
|
||||
|
||||
class FungibleFoo(override val amount: Amount<Currency>, override val participants: List<AbstractParty>) : FungibleState<Currency>
|
||||
|
||||
@Test
|
||||
fun `fungible state selection test`() {
|
||||
val issuerParty = services.myInfo.legalIdentities.first()
|
||||
@ -552,20 +554,29 @@ class NodeVaultServiceTest {
|
||||
|
||||
@Test
|
||||
fun `is ownable state relevant`() {
|
||||
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
|
||||
val wellKnownCash = Cash.State(amount, identity.party)
|
||||
val myKeys = services.keyManagementService.filterMyKeys(listOf(wellKnownCash.owner.owningKey))
|
||||
assertTrue { NodeVaultService.isRelevant(wellKnownCash, myKeys.toSet()) }
|
||||
val myAnonymousIdentity = services.keyManagementService.freshKeyAndCert(identity, false)
|
||||
val myKeys = services.keyManagementService.filterMyKeys(listOf(identity.owningKey, myAnonymousIdentity.owningKey)).toSet()
|
||||
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(identity, false)
|
||||
val anonymousCash = Cash.State(amount, anonymousIdentity.party)
|
||||
val anonymousKeys = services.keyManagementService.filterMyKeys(listOf(anonymousCash.owner.owningKey))
|
||||
assertTrue { NodeVaultService.isRelevant(anonymousCash, anonymousKeys.toSet()) }
|
||||
// Well-known owner
|
||||
assertTrue { myKeys.isOwnableStateRelevant(identity.party, participants = emptyList()) }
|
||||
// Anonymous owner
|
||||
assertTrue { myKeys.isOwnableStateRelevant(myAnonymousIdentity.party, participants = emptyList()) }
|
||||
// Unknown owner
|
||||
assertFalse { myKeys.isOwnableStateRelevant(createUnknownIdentity(), participants = emptyList()) }
|
||||
// Under target version 3 only the owner is relevant. This is to preserve backwards compatibility
|
||||
assertFalse { myKeys.isOwnableStateRelevant(createUnknownIdentity(), participants = listOf(identity.party)) }
|
||||
}
|
||||
|
||||
val thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
|
||||
val thirdPartyCash = Cash.State(amount, thirdPartyIdentity)
|
||||
val thirdPartyKeys = services.keyManagementService.filterMyKeys(listOf(thirdPartyCash.owner.owningKey))
|
||||
assertFalse { NodeVaultService.isRelevant(thirdPartyCash, thirdPartyKeys.toSet()) }
|
||||
private fun createUnknownIdentity() = AnonymousParty(generateKeyPair().public)
|
||||
|
||||
private fun Set<PublicKey>.isOwnableStateRelevant(owner: AbstractParty, participants: List<AbstractParty>): Boolean {
|
||||
class TestOwnableState : OwnableState {
|
||||
override val owner: AbstractParty get() = owner
|
||||
override val participants: List<AbstractParty> get() = participants
|
||||
override fun withNewOwner(newOwner: AbstractParty): CommandAndState = throw AbstractMethodError()
|
||||
}
|
||||
|
||||
return NodeVaultService.isRelevant(TestOwnableState(), this)
|
||||
}
|
||||
|
||||
// TODO: Unit test linear state relevancy checks
|
||||
|
Loading…
x
Reference in New Issue
Block a user