Merge commit '219624fba7e77765ede9ed6b84193736a448a553' into chrisr3-os-4-3-4.4-merge

This commit is contained in:
Chris Rankin 2019-09-24 23:06:00 +01:00
commit c0eb8c03c0
17 changed files with 196 additions and 88 deletions

View File

@ -5,7 +5,7 @@
- [ ] Have you run the unit, integration and smoke tests as described [here](https://docs.corda.net/head/testing.html)? - [ ] Have you run the unit, integration and smoke tests as described [here](https://docs.corda.net/head/testing.html)?
- [ ] If you added public APIs, did you write the JavaDocs? - [ ] If you added public APIs, did you write the JavaDocs?
- [ ] If the changes are of interest to application developers, have you added them to the [changelog](https://github.com/corda/corda/blob/master/docs/source/changelog.rst), and potentially the [release notes](https://github.com/corda/corda/blob/master/docs/source/release-notes.rst)? - [ ] If the changes are of interest to application developers, have you added them to the [changelog](https://docs.corda.net/head/changelog.html) (`/docs/source/changelog.rst`), and potentially the [release notes](https://docs.corda.net/head/release-notes.html) (`/docs/source/release-notes.rst`)?
- [ ] If you are contributing for the first time, please read the agreement in [CONTRIBUTING.md](https://github.com/corda/corda/blob/master/CONTRIBUTING.md) now and add a comment to this pull request stating that your PR is in accordance with the [Developer's Certificate of Origin](https://github.com/corda/corda/blob/master/CONTRIBUTING.md#developer-certificate-of-origin). - [ ] If you are contributing for the first time, please read the [contributor agreement](https://docs.corda.net/head/contributing.html) now and add a comment to this pull request stating that your PR is in accordance with the [Developer's Certificate of Origin](https://docs.corda.net/head/contributing.html#merging-the-changes-back-into-corda).
Thanks for your code, it's appreciated! :) Thanks for your code, it's appreciated! :)

View File

@ -117,8 +117,15 @@ buildscript {
ext.picocli_version = '3.9.6' ext.picocli_version = '3.9.6'
ext.commons_io_version = '2.6' ext.commons_io_version = '2.6'
ext.controlsfx_version = '8.40.15' ext.controlsfx_version = '8.40.15'
ext.fontawesomefx_commons_version = '11.0' if (JavaVersion.current() == JavaVersion.VERSION_11) {
ext.fontawesomefx_fontawesome_version = '4.7.0-11' // has been compiled by a more recent version of the Java Runtime (class file version 55.0)
ext.fontawesomefx_commons_version = '11.0'
ext.fontawesomefx_fontawesome_version = '4.7.0-11'
}
else {
ext.fontawesomefx_commons_version = '8.15'
ext.fontawesomefx_fontawesome_version = '4.7.0-5'
}
// Name of the IntelliJ SDK created for the deterministic Java rt.jar. // Name of the IntelliJ SDK created for the deterministic Java rt.jar.
// ext.deterministic_idea_sdk = '1.8 (Deterministic)' // ext.deterministic_idea_sdk = '1.8 (Deterministic)'

View File

@ -2,7 +2,7 @@
package net.corda.core.internal package net.corda.core.internal
import co.paralleluniverse.strands.concurrent.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import io.github.classgraph.ClassGraph import io.github.classgraph.ClassGraph
import io.github.classgraph.ScanResult import io.github.classgraph.ScanResult
import net.corda.core.DeleteForDJVM import net.corda.core.DeleteForDJVM

View File

@ -178,6 +178,11 @@ interface IdentityService {
@Suspendable @Suspendable
fun externalIdForPublicKey(publicKey: PublicKey): UUID? fun externalIdForPublicKey(publicKey: PublicKey): UUID?
/**
* This method returns all the [PublicKey]s which have been mapped to the supplied external ID.
*
* @param externalId the external ID to lookup [PublicKey]s for
*/
fun publicKeysForExternalId(externalId: UUID): Iterable<PublicKey> fun publicKeysForExternalId(externalId: UUID): Iterable<PublicKey>
} }

View File

@ -83,4 +83,4 @@ do
--name ${NODE} \ --name ${NODE} \
--network="${NETWORK_NAME}" \ --network="${NETWORK_NAME}" \
corda/${DOCKER_IMAGE_VERSION}:latest config-generator --generic corda/${DOCKER_IMAGE_VERSION}:latest config-generator --generic
done done

View File

@ -15,9 +15,17 @@ Unreleased
when rethrown on the RPC client. when rethrown on the RPC client.
* Introduced a new parameter ``externalIds: List<UUID>`` to ``VaultQueryCriteria`` which allows CorDapp developers to constrain queries * Introduced a new parameter ``externalIds: List<UUID>`` to ``VaultQueryCriteria`` which allows CorDapp developers to constrain queries
to a specified set of external IDs. to a specified set of external IDs. This feature should be used when querying states for a particular "account" (see accounts CorDapp for
further information).
* Introduced a new API on ``KeyManagementService`` which facilitates lookups of ``PublicKey`` s to ``externalId`` s (Account IDs). * Introduced a new API on ``IdentityService`` called ``RegisterKey`` which maps a ``PublicKey`` to a specified ``CordaX500Name`` and to an
optional ``UUID`` (external Id).
* Introduced a new API on ``IdentityService`` called ``publicKeyToExternalId` which facilitates lookups of ``PublicKey`` s to
``externalId`` s (Account IDs).
* Introduced a new API on ``IdentityService`` called ``publicKeysForExternalId`` which returns all the ``PublicKey`` s associated with a
particular external ID.
* ``StatePointer`` has been marked as ```@DoNotImplement``, which was an omission in the original release. * ``StatePointer`` has been marked as ```@DoNotImplement``, which was an omission in the original release.

View File

@ -6,6 +6,12 @@ apply plugin: 'net.corda.plugins.quasar-utils'
configurations { configurations {
integrationTestCompile.extendsFrom testCompile integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime integrationTestRuntime.extendsFrom testRuntime
compile {
// We already have a SLF4J implementation on our runtime classpath,
// and we don't need another one.
exclude group: "org.apache.logging.log4j"
}
} }
sourceSets { sourceSets {
@ -33,14 +39,9 @@ dependencies {
compile project(':core') compile project(':core')
compile project(':client:jfx') compile project(':client:jfx')
compile (project(':node-driver')) { compile project(':node-driver')
// We already have a SLF4J implementation on our runtime classpath, compile project(':webserver')
// and we don't need another one.
exclude group: 'org.apache.logging.log4j'
}
compile (project(':webserver')) {
exclude group: "org.apache.logging.log4j"
}
testCompile project(':test-utils') testCompile project(':test-utils')
compile "org.graphstream:gs-core:1.3" compile "org.graphstream:gs-core:1.3"
@ -49,8 +50,8 @@ dependencies {
exclude group: "junit" exclude group: "junit"
} }
compile project(path: ":node:capsule", configuration: 'runtimeArtifacts') cordaRuntime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
compile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') cordaRuntime project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
// CorDapps: dependent flows and services // CorDapps: dependent flows and services
compile project(':finance:contracts') compile project(':finance:contracts')

View File

@ -111,7 +111,6 @@ object PersistentIdentitiesMigrationSchemaBuilder {
PersistentIdentityService.PersistentPartyToPublicKeyHash::class.java, PersistentIdentityService.PersistentPartyToPublicKeyHash::class.java,
PersistentIdentityService.PersistentPublicKeyHashToParty::class.java, PersistentIdentityService.PersistentPublicKeyHashToParty::class.java,
PersistentIdentityService.PersistentHashToPublicKey::class.java, PersistentIdentityService.PersistentHashToPublicKey::class.java,
BasicHSMKeyManagementService.PersistentKey::class.java,
NodeAttachmentService.DBAttachment::class.java, NodeAttachmentService.DBAttachment::class.java,
DBNetworkParametersStorage.PersistentNetworkParameters::class.java DBNetworkParametersStorage.PersistentNetworkParameters::class.java
)) ))

View File

@ -129,7 +129,6 @@ object VaultMigrationSchemaV1 : MappedSchema(schemaFamily = VaultMigrationSchema
PersistentIdentityService.PersistentPublicKeyHashToCertificate::class.java, PersistentIdentityService.PersistentPublicKeyHashToCertificate::class.java,
PersistentIdentityService.PersistentPartyToPublicKeyHash::class.java, PersistentIdentityService.PersistentPartyToPublicKeyHash::class.java,
PersistentIdentityService.PersistentPublicKeyHashToParty::class.java, PersistentIdentityService.PersistentPublicKeyHashToParty::class.java,
PersistentIdentityService.PersistentHashToPublicKey::class.java,
BasicHSMKeyManagementService.PersistentKey::class.java, BasicHSMKeyManagementService.PersistentKey::class.java,
NodeAttachmentService.DBAttachment::class.java, NodeAttachmentService.DBAttachment::class.java,
DBNetworkParametersStorage.PersistentNetworkParameters::class.java DBNetworkParametersStorage.PersistentNetworkParameters::class.java

View File

@ -27,6 +27,7 @@ import net.corda.node.services.persistence.NodeAttachmentService
import org.hibernate.query.criteria.internal.expression.LiteralExpression import org.hibernate.query.criteria.internal.expression.LiteralExpression
import org.hibernate.query.criteria.internal.path.SingularAttributePath import org.hibernate.query.criteria.internal.path.SingularAttributePath
import org.hibernate.query.criteria.internal.predicate.ComparisonPredicate import org.hibernate.query.criteria.internal.predicate.ComparisonPredicate
import org.hibernate.query.criteria.internal.predicate.CompoundPredicate
import org.hibernate.query.criteria.internal.predicate.InPredicate import org.hibernate.query.criteria.internal.predicate.InPredicate
import java.security.PublicKey import java.security.PublicKey
import java.time.Instant import java.time.Instant
@ -409,63 +410,74 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
} }
} }
private fun getVaultFungibleStateRoot(): Root<out Any> {
val entityStateClass = VaultSchemaV1.VaultFungibleStates::class.java
return rootEntities.getOrElse(entityStateClass) {
val entityRoot = criteriaQuery.from(entityStateClass)
rootEntities[entityStateClass] = entityRoot
entityRoot
}
}
private fun getVaultLinearStatesRoot(): Root<out Any> {
val entityStateClass = VaultSchemaV1.VaultLinearStates::class.java
return rootEntities.getOrElse(entityStateClass) {
val entityRoot = criteriaQuery.from(entityStateClass)
rootEntities[entityStateClass] = entityRoot
entityRoot
}
}
private fun getPersistentPartyRoot(): Root<out Any> {
val persistentPartyEntity = VaultSchemaV1.PersistentParty::class.java
return rootEntities.getOrElse(persistentPartyEntity) {
val entityRoot = criteriaQuery.from(persistentPartyEntity)
rootEntities[persistentPartyEntity] = entityRoot
entityRoot
}
}
override fun parseCriteria(criteria: QueryCriteria.FungibleAssetQueryCriteria): Collection<Predicate> { override fun parseCriteria(criteria: QueryCriteria.FungibleAssetQueryCriteria): Collection<Predicate> {
log.trace { "Parsing FungibleAssetQueryCriteria: $criteria" } log.trace { "Parsing FungibleAssetQueryCriteria: $criteria" }
val predicateSet = mutableSetOf<Predicate>() val predicateSet = mutableSetOf<Predicate>()
// ensure we re-use any existing instance of the same root entity // ensure we re-use any existing instance of the same root entity
val entityStateClass = VaultSchemaV1.VaultFungibleStates::class.java val vaultFungibleStatesRoot = getVaultFungibleStateRoot()
val vaultFungibleStates = val joinPredicate = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"),
rootEntities.getOrElse(entityStateClass) { vaultFungibleStatesRoot.get<PersistentStateRef>("stateRef"))
val entityRoot = criteriaQuery.from(entityStateClass)
rootEntities[entityStateClass] = entityRoot
entityRoot
}
val joinPredicate = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), vaultFungibleStates.get<PersistentStateRef>("stateRef"))
predicateSet.add(joinPredicate) predicateSet.add(joinPredicate)
// owner // owner
criteria.owner?.let { criteria.owner?.let {
val owners = criteria.owner as List<AbstractParty> val owners = criteria.owner as List<AbstractParty>
predicateSet.add(criteriaBuilder.and(vaultFungibleStates.get<AbstractParty>("owner").`in`(owners))) predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("owner").`in`(owners)))
} }
// quantity // quantity
criteria.quantity?.let { criteria.quantity?.let {
predicateSet.add(columnPredicateToPredicate(vaultFungibleStates.get<Long>("quantity"), it)) predicateSet.add(columnPredicateToPredicate(vaultFungibleStatesRoot.get<Long>("quantity"), it))
} }
// issuer party // issuer party
criteria.issuer?.let { criteria.issuer?.let {
val issuerParties = criteria.issuer as List<AbstractParty> val issuerParties = criteria.issuer as List<AbstractParty>
predicateSet.add(criteriaBuilder.and(vaultFungibleStates.get<AbstractParty>("issuer").`in`(issuerParties))) predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("issuer").`in`(issuerParties)))
} }
// issuer reference // issuer reference
criteria.issuerRef?.let { criteria.issuerRef?.let {
val issuerRefs = (criteria.issuerRef as List<OpaqueBytes>).map { it.bytes } val issuerRefs = (criteria.issuerRef as List<OpaqueBytes>).map { it.bytes }
predicateSet.add(criteriaBuilder.and(vaultFungibleStates.get<ByteArray>("issuerRef").`in`(issuerRefs))) predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
} }
// Participants. // Participants.
criteria.participants?.let { criteria.participants?.let {
val participants = criteria.participants!! // Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate)
val statePartyToFungibleStatesJoin = criteriaBuilder.and(
// Get the persistent party entity. criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"),
val persistentPartyEntity = VaultSchemaV1.PersistentParty::class.java getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef")))
val entityRoot = rootEntities.getOrElse(persistentPartyEntity) { predicateSet.add(statePartyToFungibleStatesJoin)
val entityRoot = criteriaQuery.from(persistentPartyEntity)
rootEntities[persistentPartyEntity] = entityRoot
entityRoot
}
// Add the join and participants predicates.
val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))
val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
predicateSet.add(statePartyJoin)
predicateSet.add(participantsPredicate)
} }
return predicateSet return predicateSet
@ -477,47 +489,32 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
val predicateSet = mutableSetOf<Predicate>() val predicateSet = mutableSetOf<Predicate>()
// ensure we re-use any existing instance of the same root entity // ensure we re-use any existing instance of the same root entity
val entityStateClass = VaultSchemaV1.VaultLinearStates::class.java val vaultLinearStatesRoot = getVaultLinearStatesRoot()
val vaultLinearStates =
rootEntities.getOrElse(entityStateClass) {
val entityRoot = criteriaQuery.from(entityStateClass)
rootEntities[entityStateClass] = entityRoot
entityRoot
}
val joinPredicate = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), vaultLinearStates.get<PersistentStateRef>("stateRef")) val joinPredicate = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"),
vaultLinearStatesRoot.get<PersistentStateRef>("stateRef"))
predicateSet.add(joinPredicate) predicateSet.add(joinPredicate)
// linear ids UUID // linear ids UUID
criteria.uuid?.let { criteria.uuid?.let {
val uuids = criteria.uuid as List<UUID> val uuids = criteria.uuid as List<UUID>
predicateSet.add(criteriaBuilder.and(vaultLinearStates.get<UUID>("uuid").`in`(uuids))) predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<UUID>("uuid").`in`(uuids)))
} }
// linear ids externalId // linear ids externalId
criteria.externalId?.let { criteria.externalId?.let {
val externalIds = criteria.externalId as List<String> val externalIds = criteria.externalId as List<String>
if (externalIds.isNotEmpty()) if (externalIds.isNotEmpty())
predicateSet.add(criteriaBuilder.and(vaultLinearStates.get<String>("externalId").`in`(externalIds))) predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
} }
// Participants. // Participants.
criteria.participants?.let { criteria.participants?.let {
val participants = criteria.participants!! // Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate)
val statePartyToLinearStatesJoin = criteriaBuilder.and(
// Get the persistent party entity. criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"),
val persistentPartyEntity = VaultSchemaV1.PersistentParty::class.java getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef")))
val entityRoot = rootEntities.getOrElse(persistentPartyEntity) { predicateSet.add(statePartyToLinearStatesJoin)
val entityRoot = criteriaQuery.from(persistentPartyEntity)
rootEntities[persistentPartyEntity] = entityRoot
entityRoot
}
// Add the join and participants predicates.
val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))
val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
predicateSet.add(statePartyJoin)
predicateSet.add(participantsPredicate)
} }
return predicateSet return predicateSet
@ -678,6 +675,33 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
constraintPredicates.add(externalIdPredicate) constraintPredicates.add(externalIdPredicate)
} }
// Participants.
criteria.participants?.let {
val participants = criteria.participants!!
// use a single predicate for querying the persistent party table (incrementally add additional parties)
val predicateID = Pair(VaultSchemaV1.PersistentParty::x500Name.name, EQUAL)
if (commonPredicates.containsKey(predicateID)) {
val existingParticipants = ((((commonPredicates[predicateID]) as CompoundPredicate).expressions[0]) as InPredicate<*>)
.values.map { participant -> (participant as LiteralExpression<*>).literal }
log.warn("Adding new participants: $participants to existing participants: $existingParticipants")
commonPredicates.replace(predicateID, criteriaBuilder.and(
getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("x500Name").`in`(existingParticipants + participants)))
}
else {
// Get the persistent party entity.
commonPredicates[predicateID] = criteriaBuilder.and(
getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
}
// Add the join for vault states to persistent entities (if this is not a Fungible nor Linear criteria query)
if (criteria !is QueryCriteria.FungibleAssetQueryCriteria && criteria !is QueryCriteria.LinearStateQueryCriteria ) {
val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))
constraintPredicates.add(statePartyJoin)
}
}
return emptySet() return emptySet()
} }

View File

@ -25,9 +25,13 @@
<include file="migration/node-core.changelog-v13.xml"/> <include file="migration/node-core.changelog-v13.xml"/>
<!-- This change should be done before the v14-data migration. --> <!-- This change should be done before the v14-data migration. -->
<include file="migration/node-core.changelog-v15-table.xml"/> <include file="migration/node-core.changelog-v15-table.xml"/>
<include file="migration/node-core.changelog-v14-data.xml"/>
<include file="migration/node-core.changelog-v15.xml"/> <include file="migration/node-core.changelog-v15.xml"/>
<include file="migration/node-core.changelog-v16.xml"/>
<!-- This must run after node-core.changelog-init.xml, to prevent database columns being created twice. --> <!-- This must run after node-core.changelog-init.xml, to prevent database columns being created twice. -->
<include file="migration/vault-schema.changelog-v9.xml"/> <include file="migration/vault-schema.changelog-v9.xml"/>
<include file="migration/node-core.changelog-v14-data.xml"/>
</databaseChangeLog> </databaseChangeLog>

View File

@ -0,0 +1,21 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
<changeSet author="R3.Corda" id="modify public_key column type" dbms="postgresql">
<preConditions onFail="MARK_RAN">
<not>
<sqlCheck expectedResult="bytea">
SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'node_hash_to_key' AND COLUMN_NAME = 'public_key'
</sqlCheck>
</not>
</preConditions>
<dropColumn tableName="node_hash_to_key" columnName="public_key"/>
<addColumn tableName="node_hash_to_key">
<column name="public_key" type="varbinary(64000)">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@ -229,6 +229,34 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
* Query API tests * Query API tests
*/ */
/** Generic Query tests: using CommonQueryCriteria */
@Test
fun `unconsumed base contract states for single participant`() {
database.transaction {
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP))
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) // true
val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP))
val results = vaultService.queryBy<ContractState>(criteria)
assertThat(results.states).hasSize(1)
}
}
@Test
fun `unconsumed base contract states for two participants`() {
database.transaction {
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP)) // true
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) // true
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP))
val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP))
val results = vaultService.queryBy<ContractState>(criteria)
assertThat(results.states).hasSize(2)
}
}
/** Generic Query tests /** Generic Query tests
(combining both FungibleState and LinearState contract types) */ (combining both FungibleState and LinearState contract types) */
@ -2379,8 +2407,8 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY) identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
identitySvc.verifyAndRegisterIdentity(CHARLIE_IDENTITY) identitySvc.verifyAndRegisterIdentity(CHARLIE_IDENTITY)
vaultFiller.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE)) vaultFiller.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE))
vaultFiller.fillWithSomeTestLinearStates(1, "TEST2", listOf(BOB)) vaultFiller.fillWithSomeTestLinearStates(1, "TEST2", listOf(BOB))
vaultFiller.fillWithSomeTestLinearStates(1, "TEST3", listOf(CHARLIE)) vaultFiller.fillWithSomeTestLinearStates(1, "TEST3", listOf(CHARLIE))
vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER) vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER)
vaultFiller.fillWithSomeTestCommodity(Amount(100, Commodity.getInstance("FCOJ")!!), notaryServices, DUMMY_OBLIGATION_ISSUER.ref(1)) vaultFiller.fillWithSomeTestCommodity(Amount(100, Commodity.getInstance("FCOJ")!!), notaryServices, DUMMY_OBLIGATION_ISSUER.ref(1))
vaultFiller.fillWithDummyState() vaultFiller.fillWithDummyState()
@ -2397,7 +2425,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
assertThat(resultsFASC.states).hasSize(2) assertThat(resultsFASC.states).hasSize(2)
// composite query for both linear and fungible asset states by participants // composite query for both linear and fungible asset states by participants
val resultsComposite = vaultService.queryBy<ContractState>(linearStateCriteria.or(fungibleAssetStateCriteria)) val resultsComposite = vaultService.queryBy<ContractState>(linearStateCriteria.or(fungibleAssetStateCriteria))
assertThat(resultsComposite.states).hasSize(4) assertThat(resultsComposite.states).hasSize(5)
// composite query both linear and fungible and dummy asset states by participants
val commonQueryCriteria = VaultQueryCriteria(participants = listOf(MEGA_CORP))
val resultsAll = vaultService.queryBy<ContractState>(linearStateCriteria.or(fungibleAssetStateCriteria).or(commonQueryCriteria))
assertThat(resultsAll.states).hasSize(6)
} }
} }

View File

@ -6,6 +6,7 @@ import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
import net.corda.serialization.internal.model.resolveAgainst
import org.apache.qpid.proton.amqp.Symbol import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.lang.reflect.Type import java.lang.reflect.Type
@ -37,20 +38,21 @@ open class ArraySerializer(override val type: Type, factory: LocalSerializerFact
private fun calcTypeName(type: Type, debugOffset : Int = 0): String { private fun calcTypeName(type: Type, debugOffset : Int = 0): String {
logger.trace { "${"".padStart(debugOffset, ' ') } calcTypeName - ${type.typeName}" } logger.trace { "${"".padStart(debugOffset, ' ') } calcTypeName - ${type.typeName}" }
return if (type.componentType().isArray()) { val componentType = type.componentType()
return if (componentType.isArray()) {
// Special case handler for primitive byte arrays. This is needed because we can silently // Special case handler for primitive byte arrays. This is needed because we can silently
// coerce a byte[] to our own binary type. Normally, if the component type was itself an // coerce a byte[] to our own binary type. Normally, if the component type was itself an
// array we'd keep walking down the chain but for byte[] stop here and use binary instead // array we'd keep walking down the chain but for byte[] stop here and use binary instead
val typeName = if (AMQPTypeIdentifiers.isPrimitive(type.componentType())) { val typeName = if (AMQPTypeIdentifiers.isPrimitive(componentType)) {
AMQPTypeIdentifiers.nameForType(type.componentType()) AMQPTypeIdentifiers.nameForType(componentType)
} else { } else {
calcTypeName(type.componentType(), debugOffset + 4) calcTypeName(componentType, debugOffset + 4)
} }
"$typeName[]" "$typeName[]"
} else { } else {
val arrayType = if (type.asClass().componentType.isPrimitive) "[p]" else "[]" val arrayType = if (type.asClass().componentType.isPrimitive) "[p]" else "[]"
"${type.componentType().typeName}$arrayType" "${componentType.typeName}$arrayType"
} }
} }
@ -58,7 +60,7 @@ open class ArraySerializer(override val type: Type, factory: LocalSerializerFact
factory.createDescriptor(type) factory.createDescriptor(type)
} }
internal val elementType: Type by lazy { type.componentType() } internal val elementType: Type by lazy { type.componentType().resolveAgainst(type) }
internal open val typeName by lazy { calcTypeName(type) } internal open val typeName by lazy { calcTypeName(type) }
internal val typeNotation: TypeNotation by lazy { internal val typeNotation: TypeNotation by lazy {

View File

@ -209,7 +209,12 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
observedType = type, observedType = type,
typeIdentifier = typeIdentifier, typeIdentifier = typeIdentifier,
constructor = null, constructor = null,
properties = buildReadOnlyProperties(rawType), properties = if (rawType == Class::class.java) {
// Do NOT drill down into the internals of java.lang.Class.
emptyMap()
} else {
buildReadOnlyProperties(rawType)
},
superclass = superclassInformation, superclass = superclassInformation,
interfaces = interfaceInformation, interfaces = interfaceInformation,
typeParameters = typeParameterInformation, typeParameters = typeParameterInformation,

View File

@ -224,15 +224,16 @@ class VaultFiller @JvmOverloads constructor(
/** /**
* Records a dummy state in the Vault (useful for creating random states when testing vault queries) * Records a dummy state in the Vault (useful for creating random states when testing vault queries)
*/ */
fun fillWithDummyState() : Vault<DummyState> { fun fillWithDummyState(participants: List<AbstractParty> = listOf(services.myInfo.singleIdentity())) : Vault<DummyState> {
val outputState = TransactionState( val outputState = TransactionState(
data = DummyState(Random().nextInt(), participants = listOf(services.myInfo.singleIdentity())), data = DummyState(Random().nextInt(), participants = participants),
contract = DummyContract.PROGRAM_ID, contract = DummyContract.PROGRAM_ID,
notary = defaultNotary.party notary = defaultNotary.party
) )
val participantKeys : List<PublicKey> = participants.map { it.owningKey }
val builder = TransactionBuilder() val builder = TransactionBuilder()
.addOutputState(outputState) .addOutputState(outputState)
.addCommand(DummyCommandData, defaultNotary.party.owningKey) .addCommand(DummyCommandData, participantKeys)
val stxn = services.signInitialTransaction(builder) val stxn = services.signInitialTransaction(builder)
services.recordTransactions(stxn) services.recordTransactions(stxn)
return Vault(setOf(stxn.tx.outRef(0))) return Vault(setOf(stxn.tx.outRef(0)))

View File

@ -40,7 +40,7 @@ task buildWebserverJar(type: FatCapsule, dependsOn: project(':node').tasks.jar)
capsuleManifest { capsuleManifest {
applicationVersion = corda_release_version applicationVersion = corda_release_version
javaAgents = ["quasar-core-${quasar_version}.jar"] javaAgents = quasar_classifier == null ? ["quasar-core-${quasar_version}.jar"] : ["quasar-core-${quasar_version}-${quasar_classifier}.jar"]
systemProperties['visualvm.display.name'] = 'Corda Webserver' systemProperties['visualvm.display.name'] = 'Corda Webserver'
minJavaVersion = '1.8.0' minJavaVersion = '1.8.0'
minUpdateVersion['1.8'] = java8_minUpdateVersion minUpdateVersion['1.8'] = java8_minUpdateVersion