mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Merge branch 'release/os/4.10' into shams-4.11-merge-53fe0e6c
# Conflicts: # node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt
This commit is contained in:
commit
fe416879cd
@ -272,7 +272,7 @@ class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder:
|
||||
class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractState>,
|
||||
val contractStateTypeMappings: Map<String, Set<String>>,
|
||||
override val criteriaBuilder: CriteriaBuilder,
|
||||
val criteriaQuery: CriteriaQuery<Tuple>,
|
||||
val criteriaQuery: CriteriaQuery<*>,
|
||||
val vaultStates: Root<VaultSchemaV1.VaultStates>) : AbstractQueryCriteriaParser<QueryCriteria, IQueryCriteriaParser, Sort>(), IQueryCriteriaParser {
|
||||
private companion object {
|
||||
private val log = contextLogger()
|
||||
|
@ -35,7 +35,6 @@ import net.corda.core.node.services.vault.PageSpecification
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.node.services.vault.Sort
|
||||
import net.corda.core.node.services.vault.SortAttribute
|
||||
import net.corda.core.node.services.vault.builder
|
||||
import net.corda.core.observable.internal.OnResilientSubscribe
|
||||
import net.corda.core.schemas.PersistentStateRef
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
@ -69,17 +68,21 @@ import java.security.PublicKey
|
||||
import java.sql.SQLException
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.util.Arrays
|
||||
import java.util.UUID
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import java.util.stream.Stream
|
||||
import javax.persistence.PersistenceException
|
||||
import javax.persistence.Tuple
|
||||
import javax.persistence.criteria.CriteriaBuilder
|
||||
import javax.persistence.criteria.CriteriaQuery
|
||||
import javax.persistence.criteria.CriteriaUpdate
|
||||
import javax.persistence.criteria.Predicate
|
||||
import javax.persistence.criteria.Root
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.LinkedHashSet
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
|
||||
/**
|
||||
* The vault service handles storage, retrieval and querying of states.
|
||||
@ -707,10 +710,8 @@ class NodeVaultService(
|
||||
paging: PageSpecification,
|
||||
sorting: Sort,
|
||||
contractStateType: Class<out T>): Vault.Page<T> {
|
||||
// calculate total results where a page specification has been defined
|
||||
val totalStatesAvailable = if (paging.isDefault) -1 else queryTotalStateCount(criteria, contractStateType)
|
||||
|
||||
val (query, stateTypes) = createQuery(criteria, contractStateType, sorting)
|
||||
val (criteriaQuery, criteriaParser) = buildCriteriaQuery<Tuple>(criteria, contractStateType, sorting)
|
||||
val query = getSession().createQuery(criteriaQuery)
|
||||
query.setResultWindow(paging)
|
||||
|
||||
var previousPageAnchor: StateRef? = null
|
||||
@ -742,7 +743,14 @@ class NodeVaultService(
|
||||
ArrayList()
|
||||
)
|
||||
|
||||
return Vault.Page(states, statesMetadata, totalStatesAvailable, stateTypes, otherResults, previousPageAnchor)
|
||||
val totalStatesAvailable = when {
|
||||
paging.isDefault -> -1L
|
||||
// If the first page isn't full then we know that's all the states that are available
|
||||
paging.pageNumber == DEFAULT_PAGE_NUM && states.size < paging.pageSize -> states.size.toLong()
|
||||
else -> queryTotalStateCount(criteria, contractStateType)
|
||||
}
|
||||
|
||||
return Vault.Page(states, statesMetadata, totalStatesAvailable, criteriaParser.stateTypes, otherResults, previousPageAnchor)
|
||||
}
|
||||
|
||||
private fun <R> Query<R>.resultStream(paging: PageSpecification): Stream<R> {
|
||||
@ -775,19 +783,17 @@ class NodeVaultService(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : ContractState> queryTotalStateCount(baseCriteria: QueryCriteria, contractStateType: Class<out T>): Long {
|
||||
val count = builder { VaultSchemaV1.VaultStates::recordedTime.count() }
|
||||
val countCriteria = QueryCriteria.VaultCustomQueryCriteria(count, Vault.StateStatus.ALL)
|
||||
val criteria = baseCriteria.and(countCriteria)
|
||||
val (query) = createQuery(criteria, contractStateType, null)
|
||||
val results = query.resultList
|
||||
return results.last().toArray().last() as Long
|
||||
private fun <T : ContractState> queryTotalStateCount(criteria: QueryCriteria, contractStateType: Class<out T>): Long {
|
||||
val (criteriaQuery, criteriaParser) = buildCriteriaQuery<Long>(criteria, contractStateType, null)
|
||||
criteriaQuery.select(criteriaBuilder.countDistinct(criteriaParser.vaultStates))
|
||||
val query = getSession().createQuery(criteriaQuery)
|
||||
return query.singleResult
|
||||
}
|
||||
|
||||
private fun <T : ContractState> createQuery(criteria: QueryCriteria,
|
||||
contractStateType: Class<out T>,
|
||||
sorting: Sort?): Pair<Query<Tuple>, Vault.StateStatus> {
|
||||
val criteriaQuery = criteriaBuilder.createQuery(Tuple::class.java)
|
||||
private inline fun <reified T> buildCriteriaQuery(criteria: QueryCriteria,
|
||||
contractStateType: Class<out ContractState>,
|
||||
sorting: Sort?): Pair<CriteriaQuery<T>, HibernateQueryCriteriaParser> {
|
||||
val criteriaQuery = criteriaBuilder.createQuery(T::class.java)
|
||||
val criteriaParser = HibernateQueryCriteriaParser(
|
||||
contractStateType,
|
||||
contractStateTypeMappings,
|
||||
@ -796,8 +802,7 @@ class NodeVaultService(
|
||||
criteriaQuery.from(VaultSchemaV1.VaultStates::class.java)
|
||||
)
|
||||
criteriaParser.parse(criteria, sorting)
|
||||
val query = getSession().createQuery(criteriaQuery)
|
||||
return Pair(query, criteriaParser.stateTypes)
|
||||
return Pair(criteriaQuery, criteriaParser)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ class VaultQueryExceptionsTests : VaultQueryParties by rule {
|
||||
|
||||
@ClassRule
|
||||
@JvmField
|
||||
val rule = object : VaultQueryTestRule() {
|
||||
val rule = object : VaultQueryTestRule(persistentServices = false) {
|
||||
override val cordappPackages = listOf(
|
||||
"net.corda.testing.contracts",
|
||||
"net.corda.finance.contracts",
|
||||
|
@ -4,6 +4,7 @@ import com.nhaarman.mockito_kotlin.mock
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.packageName
|
||||
@ -37,6 +38,7 @@ import net.corda.testing.internal.configureDatabase
|
||||
import net.corda.testing.internal.vault.*
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndPersistentServices
|
||||
import net.corda.testing.node.makeTestIdentityService
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatCode
|
||||
@ -102,7 +104,7 @@ interface VaultQueryParties {
|
||||
val cordappPackages: List<String>
|
||||
}
|
||||
|
||||
open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
|
||||
open class VaultQueryTestRule(private val persistentServices: Boolean) : ExternalResource(), VaultQueryParties {
|
||||
override val alice = TestIdentity(ALICE_NAME, 70)
|
||||
override val bankOfCorda = TestIdentity(BOC_NAME)
|
||||
override val bigCorp = TestIdentity(CordaX500Name("BigCorporation", "New York", "US"))
|
||||
@ -135,12 +137,22 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
|
||||
|
||||
|
||||
override fun before() {
|
||||
// register additional identities
|
||||
val databaseAndServices = makeTestDatabaseAndMockServices(
|
||||
cordappPackages,
|
||||
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
|
||||
megaCorp,
|
||||
moreKeys = *arrayOf(DUMMY_NOTARY_KEY))
|
||||
val databaseAndServices = if (persistentServices) {
|
||||
makeTestDatabaseAndPersistentServices(
|
||||
cordappPackages,
|
||||
megaCorp,
|
||||
moreKeys = setOf(DUMMY_NOTARY_KEY),
|
||||
moreIdentities = setOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity)
|
||||
)
|
||||
} else {
|
||||
@Suppress("SpreadOperator")
|
||||
makeTestDatabaseAndMockServices(
|
||||
cordappPackages,
|
||||
makeTestIdentityService(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, dummyCashIssuer.identity, dummyNotary.identity),
|
||||
megaCorp,
|
||||
moreKeys = *arrayOf(DUMMY_NOTARY_KEY)
|
||||
)
|
||||
}
|
||||
database = databaseAndServices.first
|
||||
services = databaseAndServices.second
|
||||
vaultFiller = VaultFiller(services, dummyNotary)
|
||||
@ -2890,9 +2902,8 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
}
|
||||
|
||||
class VaultQueryTests : VaultQueryTestsBase(), VaultQueryParties by delegate {
|
||||
|
||||
companion object {
|
||||
val delegate = VaultQueryTestRule()
|
||||
val delegate = VaultQueryTestRule(persistentServices = false)
|
||||
}
|
||||
|
||||
@Rule
|
||||
@ -3195,4 +3206,34 @@ class VaultQueryTests : VaultQueryTestsBase(), VaultQueryParties by delegate {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PersistentServicesVaultQueryTests : VaultQueryParties by delegate {
|
||||
companion object {
|
||||
val delegate = VaultQueryTestRule(persistentServices = true)
|
||||
|
||||
@ClassRule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val vaultQueryTestRule = delegate
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `query on externalId which maps to multiple keys`() {
|
||||
val externalId = UUID.randomUUID()
|
||||
val page = database.transaction {
|
||||
val keys = Array(2) { services.keyManagementService.freshKey(externalId) }
|
||||
vaultFiller.fillWithDummyState(participants = keys.map(::AnonymousParty))
|
||||
services.vaultService.queryBy<ContractState>(
|
||||
VaultQueryCriteria(externalIds = listOf(externalId)),
|
||||
paging = PageSpecification(DEFAULT_PAGE_NUM, 10)
|
||||
)
|
||||
}
|
||||
assertThat(page.states).hasSize(1)
|
||||
assertThat(page.totalStatesAvailable).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
@ -637,6 +637,45 @@ class EvolvabilityTests {
|
||||
assertEquals(DUMMY_NOTARY_PARTY, networkParams.notaries.firstOrNull()?.identity)
|
||||
}
|
||||
|
||||
//
|
||||
// This test uses a NetworkParameters signed set of bytes generated by a Corda 4.11 build and
|
||||
// is here to ensure we can still read them. This test exists because Corda 4.11 Adds in new
|
||||
// network parameters that should be backwards compatible with older corda versions
|
||||
//
|
||||
// The file itself was generated from a corda-os 4.11 build at commit
|
||||
// 58ecce1 Ent-9875: New Network Parameters
|
||||
//
|
||||
// To regenerate the file un-ignore the test below this one (regenerate broken network parameters),
|
||||
// to regenerate at a specific version add that test to a checkout at the desired sha then take
|
||||
// the resulting file and add to the repo, changing the filename as appropriate
|
||||
//
|
||||
@Test(timeout=300_000)
|
||||
fun `read corda 4-11 network parameters`() {
|
||||
val sf = testDefaultFactory()
|
||||
sf.register(net.corda.serialization.internal.amqp.custom.InstantSerializer(sf))
|
||||
sf.register(net.corda.serialization.internal.amqp.custom.PublicKeySerializer)
|
||||
sf.register(net.corda.serialization.internal.amqp.custom.DurationSerializer(sf))
|
||||
|
||||
//
|
||||
// filename breakdown
|
||||
// networkParams - because this is a serialised set of network parameters
|
||||
// r3corda - generated by Corda Enterprise instead of Corda
|
||||
// 6a6b6f256 - Commit sha of the build that generated the file we're testing against
|
||||
//
|
||||
val resource = "networkParams.4.11.58ecce1"
|
||||
|
||||
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||
val sc2 = url.readBytes()
|
||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<SignedData<NetworkParameters>>(sc2))
|
||||
val networkParams = DeserializationInput(sf).deserialize(deserializedC.raw)
|
||||
|
||||
assertEquals(1000, networkParams.maxMessageSize)
|
||||
assertEquals(1000, networkParams.maxTransactionSize)
|
||||
assertEquals(3, networkParams.minimumPlatformVersion)
|
||||
assertEquals(1, networkParams.notaries.size)
|
||||
assertEquals(DUMMY_NOTARY_PARTY, networkParams.notaries.firstOrNull()?.identity)
|
||||
}
|
||||
|
||||
//
|
||||
// This test created a serialized and signed set of Network Parameters to test whether we
|
||||
// can still deserialize them
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user