mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
Vault identity cleanup (#1194)
* Removed notary_key (and all references) from vault schema. Fixed incorrect NOTARY usage in certain tests (cash consumption) * Fixed broken test. * Replace CommonSchemaV1.Party in all VaultSchema tables (and associated queries) with string'ified X500Name's only. * Fix broken tests. * Completely remove CommonSchemaV1.Party and all references (in favour of X500Name's) * Updated all schema attribute identity references to use AbstractParty. * Updated all schema attribute identity references to use AbstractParty. * Standarised attribute naming for parties (removed 'Name') * Updated deprecate identity API references following rebase. * Configurable IdentityService as a lambda in JUnit tests. * Additional WARNING logging to enable troubleshooting of identity lookup failures. * Final identity updates to sample schemas. Cleaned up several compiler warnings.
This commit is contained in:
parent
dc8d232480
commit
48e8aa55fa
@ -5,6 +5,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.toFuture
|
||||
@ -135,8 +136,7 @@ class Vault<out T : ContractState>(val states: Iterable<StateAndRef<T>>) {
|
||||
val recordedTime: Instant,
|
||||
val consumedTime: Instant?,
|
||||
val status: Vault.StateStatus,
|
||||
val notaryName: String,
|
||||
val notaryKey: String,
|
||||
val notary: AbstractParty?,
|
||||
val lockId: String?,
|
||||
val lockUpdateTime: Instant?)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ sealed class QueryCriteria {
|
||||
data class VaultQueryCriteria @JvmOverloads constructor (override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
val contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
val stateRefs: List<StateRef>? = null,
|
||||
val notaryName: List<X500Name>? = null,
|
||||
val notary: List<AbstractParty>? = null,
|
||||
val softLockingCondition: SoftLockingCondition? = null,
|
||||
val timeCondition: TimeCondition? = null) : CommonQueryCriteria() {
|
||||
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
||||
@ -81,7 +81,7 @@ sealed class QueryCriteria {
|
||||
data class FungibleAssetQueryCriteria @JvmOverloads constructor(val participants: List<AbstractParty>? = null,
|
||||
val owner: List<AbstractParty>? = null,
|
||||
val quantity: ColumnPredicate<Long>? = null,
|
||||
val issuerPartyName: List<AbstractParty>? = null,
|
||||
val issuer: List<AbstractParty>? = null,
|
||||
val issuerRef: List<OpaqueBytes>? = null,
|
||||
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED) : CommonQueryCriteria() {
|
||||
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
||||
|
@ -151,7 +151,7 @@ data class Sort(val columns: Collection<SortColumn>) {
|
||||
|
||||
enum class VaultStateAttribute(val attributeName: String) : Attribute {
|
||||
/** Vault States */
|
||||
NOTARY_NAME("notaryName"),
|
||||
NOTARY_NAME("notary"),
|
||||
CONTRACT_TYPE("contractStateClassName"),
|
||||
STATE_STATUS("stateStatus"),
|
||||
RECORDED_TIME("recordedTime"),
|
||||
|
@ -17,10 +17,17 @@ object CommonSchema
|
||||
/**
|
||||
* First version of the Vault ORM schema
|
||||
*/
|
||||
object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, version = 1, mappedTypes = listOf(Party::class.java)) {
|
||||
object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, version = 1, mappedTypes = emptyList()) {
|
||||
|
||||
@MappedSuperclass
|
||||
open class LinearState(
|
||||
/** [ContractState] attributes */
|
||||
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
@Column(name = "participants")
|
||||
var participants: MutableSet<AbstractParty>? = null,
|
||||
|
||||
/**
|
||||
* Represents a [LinearState] [UniqueIdentifier]
|
||||
*/
|
||||
@ -31,18 +38,26 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
|
||||
var uuid: UUID
|
||||
|
||||
) : PersistentState() {
|
||||
constructor(uid: UniqueIdentifier) : this(externalId = uid.externalId, uuid = uid.id)
|
||||
constructor(uid: UniqueIdentifier, _participants: Set<AbstractParty>)
|
||||
: this(participants = _participants.toMutableSet(),
|
||||
externalId = uid.externalId,
|
||||
uuid = uid.id)
|
||||
}
|
||||
|
||||
@MappedSuperclass
|
||||
open class FungibleState(
|
||||
/** [ContractState] attributes */
|
||||
@OneToMany(cascade = arrayOf(CascadeType.ALL))
|
||||
var participants: Set<CommonSchemaV1.Party>,
|
||||
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
@Column(name = "participants")
|
||||
var participants: MutableSet<AbstractParty>? = null,
|
||||
|
||||
/** [OwnableState] attributes */
|
||||
@OneToOne(cascade = arrayOf(CascadeType.ALL))
|
||||
var ownerKey: CommonSchemaV1.Party,
|
||||
|
||||
/** X500Name of owner party **/
|
||||
@Column(name = "owner_name")
|
||||
var owner: AbstractParty,
|
||||
|
||||
/** [FungibleAsset] attributes
|
||||
*
|
||||
@ -55,42 +70,12 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
|
||||
var quantity: Long,
|
||||
|
||||
/** Issuer attributes */
|
||||
@OneToOne(cascade = arrayOf(CascadeType.ALL))
|
||||
var issuerParty: CommonSchemaV1.Party,
|
||||
|
||||
/** X500Name of issuer party **/
|
||||
@Column(name = "issuer_name")
|
||||
var issuer: AbstractParty,
|
||||
|
||||
@Column(name = "issuer_reference")
|
||||
var issuerRef: ByteArray
|
||||
) : PersistentState() {
|
||||
constructor(_participants: Set<AbstractParty>, _ownerKey: AbstractParty, _quantity: Long, _issuerParty: AbstractParty, _issuerRef: ByteArray)
|
||||
: this(participants = _participants.map { CommonSchemaV1.Party(it) }.toSet(),
|
||||
ownerKey = CommonSchemaV1.Party(_ownerKey),
|
||||
quantity = _quantity,
|
||||
issuerParty = CommonSchemaV1.Party(_issuerParty),
|
||||
issuerRef = _issuerRef)
|
||||
}
|
||||
|
||||
/**
|
||||
* Party entity (to be replaced by referencing final Identity Schema)
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "vault_party",
|
||||
indexes = arrayOf(Index(name = "party_name_idx", columnList = "party_name")))
|
||||
class Party(
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@Column(name = "party_id")
|
||||
var id: Int,
|
||||
|
||||
/**
|
||||
* [Party] attributes
|
||||
*/
|
||||
@Column(name = "party_name")
|
||||
var name: String,
|
||||
|
||||
@Column(name = "party_key", length = 65535) // TODO What is the upper limit on size of CompositeKey?)
|
||||
var key: String
|
||||
) {
|
||||
constructor(party: AbstractParty)
|
||||
: this(0, party.nameOrNull()?.toString() ?: party.toString(), party.owningKey.toBase58String())
|
||||
}
|
||||
) : PersistentState()
|
||||
}
|
@ -2,6 +2,7 @@ package net.corda.core.schemas.converters
|
||||
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import javax.persistence.AttributeConverter
|
||||
import javax.persistence.Converter
|
||||
@ -17,9 +18,15 @@ class AbstractPartyToX500NameAsStringConverter(identitySvc: () -> IdentityServic
|
||||
identitySvc()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val log = loggerFor<AbstractPartyToX500NameAsStringConverter>()
|
||||
}
|
||||
|
||||
override fun convertToDatabaseColumn(party: AbstractParty?): String? {
|
||||
party?.let {
|
||||
return identityService.partyFromAnonymous(party)?.toString()
|
||||
val partyName = identityService.partyFromAnonymous(party)?.toString()
|
||||
if (partyName != null) return partyName
|
||||
else log.warn ("Identity service unable to resolve AbstractParty: $party")
|
||||
}
|
||||
return null // non resolvable anonymous parties
|
||||
}
|
||||
@ -27,7 +34,8 @@ class AbstractPartyToX500NameAsStringConverter(identitySvc: () -> IdentityServic
|
||||
override fun convertToEntityAttribute(dbData: String?): AbstractParty? {
|
||||
dbData?.let {
|
||||
val party = identityService.partyFromX500Name(X500Name(dbData))
|
||||
return party as AbstractParty
|
||||
if (party != null) return party
|
||||
else log.warn ("Identity service unable to resolve X500name: $dbData")
|
||||
}
|
||||
return null // non resolvable anonymous parties are stored as nulls
|
||||
}
|
||||
|
@ -44,11 +44,14 @@ class ContractUpgradeFlowTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork()
|
||||
val nodes = mockNet.createSomeNodes()
|
||||
val nodes = mockNet.createSomeNodes(notaryKeyPair = null) // prevent generation of notary override
|
||||
a = nodes.partyNodes[0]
|
||||
b = nodes.partyNodes[1]
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
|
||||
val nodeIdentity = nodes.notaryNode.info.legalIdentitiesAndCerts.single { it.party == nodes.notaryNode.info.notaryIdentity }
|
||||
a.services.identityService.registerIdentity(nodeIdentity)
|
||||
b.services.identityService.registerIdentity(nodeIdentity)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -12,6 +12,7 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatedBy
|
||||
import net.corda.core.flows.InitiatingFlow
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
@ -42,8 +43,8 @@ private fun gatherOurInputs(serviceHub: ServiceHub,
|
||||
val ourParties = ourKeys.map { serviceHub.identityService.partyFromKey(it) ?: throw IllegalStateException("Unable to resolve party from key") }
|
||||
val fungibleCriteria = QueryCriteria.FungibleAssetQueryCriteria(owner = ourParties)
|
||||
|
||||
val notaryName = if (notary != null) notary.name else serviceHub.networkMapCache.getAnyNotary()!!.name
|
||||
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notaryName = listOf(notaryName))
|
||||
val notaries = notary ?: serviceHub.networkMapCache.getAnyNotary()
|
||||
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notaries as AbstractParty))
|
||||
|
||||
val logicalExpression = builder { CashSchemaV1.PersistentCashState::currency.equal(amountRequired.token.product.currencyCode) }
|
||||
val cashCriteria = QueryCriteria.VaultCustomQueryCriteria(logicalExpression)
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.crypto.testing.NULL_PARTY
|
||||
import net.corda.core.crypto.toBase58String
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.Emoji
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.StatesNotAvailableException
|
||||
@ -98,7 +99,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
override fun generateMappedObject(schema: MappedSchema): PersistentState {
|
||||
return when (schema) {
|
||||
is CashSchemaV1 -> CashSchemaV1.PersistentCashState(
|
||||
owner = this.owner.owningKey.toBase58String(),
|
||||
owner = this.owner,
|
||||
pennies = this.amount.quantity,
|
||||
currency = this.amount.token.product.currencyCode,
|
||||
issuerParty = this.amount.token.issuer.party.owningKey.toBase58String(),
|
||||
@ -323,7 +324,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
AND (vs.lock_id = '$lockId' OR vs.lock_id is null)
|
||||
""" +
|
||||
(if (notary != null)
|
||||
" AND vs.notary_key = '${notary.owningKey.toBase58String()}'" else "") +
|
||||
" AND vs.notary_name = '${notary.name}'" else "") +
|
||||
(if (onlyFromIssuerParties.isNotEmpty())
|
||||
" AND ccs.issuer_key IN ($issuerKeysStr)" else "") +
|
||||
(if (withIssuerRefs.isNotEmpty())
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.schemas
|
||||
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.schemas.PersistentState
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -21,8 +22,9 @@ object CashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version
|
||||
indexes = arrayOf(Index(name = "ccy_code_idx", columnList = "ccy_code"),
|
||||
Index(name = "pennies_idx", columnList = "pennies")))
|
||||
class PersistentCashState(
|
||||
@Column(name = "owner_key")
|
||||
var owner: String,
|
||||
/** X500Name of owner party **/
|
||||
@Column(name = "owner_name")
|
||||
var owner: AbstractParty,
|
||||
|
||||
@Column(name = "pennies")
|
||||
var pennies: Long,
|
||||
|
@ -54,7 +54,7 @@ class DummyFungibleContract : OnLedgerAsset<Currency, DummyFungibleContract.Comm
|
||||
issuerRef = this.amount.token.issuer.reference.bytes
|
||||
)
|
||||
is SampleCashSchemaV2 -> SampleCashSchemaV2.PersistentCashState(
|
||||
_participants = this.participants.toSet(),
|
||||
_participants = this.participants.toMutableSet(),
|
||||
_owner = this.owner,
|
||||
_quantity = this.amount.quantity,
|
||||
currency = this.amount.token.product.currencyCode,
|
||||
@ -62,12 +62,12 @@ class DummyFungibleContract : OnLedgerAsset<Currency, DummyFungibleContract.Comm
|
||||
_issuerRef = this.amount.token.issuer.reference.bytes
|
||||
)
|
||||
is SampleCashSchemaV3 -> SampleCashSchemaV3.PersistentCashState(
|
||||
_participants = this.participants.toSet(),
|
||||
_owner = this.owner,
|
||||
_quantity = this.amount.quantity,
|
||||
_currency = this.amount.token.product.currencyCode,
|
||||
_issuerParty = this.amount.token.issuer.party,
|
||||
_issuerRef = this.amount.token.issuer.reference.bytes
|
||||
participants = this.participants.toMutableSet(),
|
||||
owner = this.owner,
|
||||
pennies = this.amount.quantity,
|
||||
currency = this.amount.token.product.currencyCode,
|
||||
issuer = this.amount.token.issuer.party,
|
||||
issuerRef = this.amount.token.issuer.reference.bytes
|
||||
)
|
||||
else -> throw IllegalArgumentException("Unrecognised schema $schema")
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import javax.persistence.Table
|
||||
* [VaultFungibleState] abstract schema
|
||||
*/
|
||||
object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, version = 2,
|
||||
mappedTypes = listOf(PersistentCashState::class.java, CommonSchemaV1.Party::class.java)) {
|
||||
mappedTypes = listOf(PersistentCashState::class.java)) {
|
||||
@Entity
|
||||
@Table(name = "cash_states_v2",
|
||||
indexes = arrayOf(Index(name = "ccy_code_idx2", columnList = "ccy_code")))
|
||||
@ -33,5 +33,5 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
|
||||
val _issuerParty: AbstractParty,
|
||||
@Transient
|
||||
val _issuerRef: ByteArray
|
||||
) : CommonSchemaV1.FungibleState(_participants, _owner, _quantity, _issuerParty, _issuerRef)
|
||||
) : CommonSchemaV1.FungibleState(_participants.toMutableSet(), _owner, _quantity, _issuerParty, _issuerRef)
|
||||
}
|
||||
|
@ -11,16 +11,19 @@ import javax.persistence.*
|
||||
* at the time of writing.
|
||||
*/
|
||||
object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, version = 3,
|
||||
mappedTypes = listOf(PersistentCashState::class.java, CommonSchemaV1.Party::class.java)) {
|
||||
mappedTypes = listOf(PersistentCashState::class.java)) {
|
||||
@Entity
|
||||
@Table(name = "cash_states_v3")
|
||||
class PersistentCashState(
|
||||
/** [ContractState] attributes */
|
||||
@OneToMany(cascade = arrayOf(CascadeType.ALL))
|
||||
var participants: Set<CommonSchemaV1.Party>,
|
||||
|
||||
@OneToOne(cascade = arrayOf(CascadeType.ALL))
|
||||
var owner: CommonSchemaV1.Party,
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
var participants: MutableSet<AbstractParty>? = null,
|
||||
|
||||
/** X500Name of owner party **/
|
||||
@Column(name = "owner_name")
|
||||
var owner: AbstractParty,
|
||||
|
||||
@Column(name = "pennies")
|
||||
var pennies: Long,
|
||||
@ -28,18 +31,11 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
|
||||
@Column(name = "ccy_code", length = 3)
|
||||
var currency: String,
|
||||
|
||||
@OneToOne(cascade = arrayOf(CascadeType.ALL))
|
||||
var issuerParty: CommonSchemaV1.Party,
|
||||
/** X500Name of issuer party **/
|
||||
@Column(name = "issuer_name")
|
||||
var issuer: AbstractParty,
|
||||
|
||||
@Column(name = "issuer_ref")
|
||||
var issuerRef: ByteArray
|
||||
) : PersistentState() {
|
||||
constructor(_participants: Set<AbstractParty>, _owner: AbstractParty, _quantity: Long, _currency: String, _issuerParty: AbstractParty, _issuerRef: ByteArray)
|
||||
: this(participants = _participants.map { CommonSchemaV1.Party(it) }.toSet(),
|
||||
owner = CommonSchemaV1.Party(_owner),
|
||||
pennies = _quantity,
|
||||
currency = _currency,
|
||||
issuerParty = CommonSchemaV1.Party(_issuerParty),
|
||||
issuerRef = _issuerRef)
|
||||
}
|
||||
) : PersistentState()
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import javax.persistence.Table
|
||||
* [VaultFungibleState] abstract schema
|
||||
*/
|
||||
object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPaperSchema.javaClass, version = 1,
|
||||
mappedTypes = listOf(PersistentCommercialPaperState::class.java, CommonSchemaV1.Party::class.java)) {
|
||||
mappedTypes = listOf(PersistentCommercialPaperState::class.java)) {
|
||||
@Entity
|
||||
@Table(name = "cp_states_v2",
|
||||
indexes = arrayOf(Index(name = "ccy_code_index2", columnList = "ccy_code"),
|
||||
@ -44,5 +44,5 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap
|
||||
val _issuerParty: AbstractParty,
|
||||
@Transient
|
||||
val _issuerRef: ByteArray
|
||||
) : CommonSchemaV1.FungibleState(_participants, _owner, _quantity, _issuerParty, _issuerRef)
|
||||
) : CommonSchemaV1.FungibleState(_participants.toMutableSet(), _owner, _quantity, _issuerParty, _issuerRef)
|
||||
}
|
||||
|
@ -41,9 +41,6 @@ object VaultSchema {
|
||||
@get:Column(name = "notary_name")
|
||||
var notaryName: String
|
||||
|
||||
@get:Column(name = "notary_key", length = 65535) // TODO What is the upper limit on size of CompositeKey?
|
||||
var notaryKey: String
|
||||
|
||||
/** references a concrete ContractState that is [QueryableState] and has a [MappedSchema] */
|
||||
@get:Column(name = "contract_state_class_name")
|
||||
var contractStateClassName: String
|
||||
|
@ -314,7 +314,6 @@ class VaultSchemaTest : TestDependencyInjectionBase() {
|
||||
contractStateClassName = state.data.javaClass.name
|
||||
contractState = state.serialize().bytes
|
||||
notaryName = state.notary.name.toString()
|
||||
notaryKey = state.notary.owningKey.toBase58String()
|
||||
recordedTime = Instant.now()
|
||||
}
|
||||
}
|
||||
@ -655,15 +654,12 @@ class VaultSchemaTest : TestDependencyInjectionBase() {
|
||||
|
||||
@Test
|
||||
fun insertWithBigCompositeKey() {
|
||||
val keys = (1..314).map { generateKeyPair().public }
|
||||
val bigNotaryKey = CompositeKey.Builder().addKeys(keys).build()
|
||||
val vaultStEntity = VaultStatesEntity().apply {
|
||||
txId = SecureHash.randomSHA256().toString()
|
||||
index = 314
|
||||
stateStatus = Vault.StateStatus.UNCONSUMED
|
||||
contractStateClassName = VaultNoopContract.VaultNoopState::class.java.name
|
||||
notaryName = "Huge distributed notary"
|
||||
notaryKey = bigNotaryKey.toBase58String()
|
||||
recordedTime = Instant.now()
|
||||
}
|
||||
data.insert(vaultStEntity)
|
||||
|
@ -7,14 +7,12 @@ import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.VaultQueryException
|
||||
import net.corda.core.node.services.vault.*
|
||||
import net.corda.core.node.services.vault.QueryCriteria.CommonQueryCriteria
|
||||
import net.corda.core.schemas.CommonSchemaV1
|
||||
import net.corda.core.schemas.PersistentState
|
||||
import net.corda.core.schemas.PersistentStateRef
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.toHexString
|
||||
import net.corda.core.utilities.trace
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.util.*
|
||||
import javax.persistence.Tuple
|
||||
import javax.persistence.criteria.*
|
||||
@ -68,9 +66,8 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
|
||||
}
|
||||
|
||||
// notary names
|
||||
criteria.notaryName?.let {
|
||||
val notaryNames = (criteria.notaryName as List<X500Name>).map { it.toString() }
|
||||
predicateSet.add(criteriaBuilder.and(vaultStates.get<String>("notaryName").`in`(notaryNames)))
|
||||
criteria.notary?.let {
|
||||
predicateSet.add(criteriaBuilder.and(vaultStates.get<AbstractParty>("notary").`in`(criteria.notary)))
|
||||
}
|
||||
|
||||
// state references
|
||||
@ -243,10 +240,8 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
|
||||
|
||||
// owner
|
||||
criteria.owner?.let {
|
||||
val ownerKeys = criteria.owner as List<AbstractParty>
|
||||
val joinFungibleStateToParty = vaultFungibleStates.join<VaultSchemaV1.VaultFungibleStates, CommonSchemaV1.Party>("issuerParty")
|
||||
val owners = ownerKeys.map { it.nameOrNull()?.toString() ?: it.toString()}
|
||||
predicateSet.add(criteriaBuilder.and(joinFungibleStateToParty.get<CommonSchemaV1.Party>("name").`in`(owners)))
|
||||
val owners = criteria.owner as List<AbstractParty>
|
||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStates.get<AbstractParty>("owner").`in`(owners)))
|
||||
}
|
||||
|
||||
// quantity
|
||||
@ -255,11 +250,9 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
|
||||
}
|
||||
|
||||
// issuer party
|
||||
criteria.issuerPartyName?.let {
|
||||
val issuerParties = criteria.issuerPartyName as List<AbstractParty>
|
||||
val joinFungibleStateToParty = vaultFungibleStates.join<VaultSchemaV1.VaultFungibleStates, CommonSchemaV1.Party>("issuerParty")
|
||||
val issuerPartyNames = issuerParties.map { it.nameOrNull().toString() }
|
||||
predicateSet.add(criteriaBuilder.and(joinFungibleStateToParty.get<CommonSchemaV1.Party>("name").`in`(issuerPartyNames)))
|
||||
criteria.issuer?.let {
|
||||
val issuerParties = criteria.issuer as List<AbstractParty>
|
||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStates.get<AbstractParty>("issuer").`in`(issuerParties)))
|
||||
}
|
||||
|
||||
// issuer reference
|
||||
@ -271,9 +264,8 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
|
||||
// participants
|
||||
criteria.participants?.let {
|
||||
val participants = criteria.participants as List<AbstractParty>
|
||||
val joinFungibleStateToParty = vaultFungibleStates.join<VaultSchemaV1.VaultFungibleStates, CommonSchemaV1.Party>("participants")
|
||||
val participantKeys = participants.map { it.nameOrNull().toString() }
|
||||
predicateSet.add(criteriaBuilder.and(joinFungibleStateToParty.get<CommonSchemaV1.Party>("name").`in`(participantKeys)))
|
||||
val joinLinearStateToParty = vaultFungibleStates.joinSet<VaultSchemaV1.VaultLinearStates, AbstractParty>("participants")
|
||||
predicateSet.add(criteriaBuilder.and(joinLinearStateToParty.`in`(participants)))
|
||||
criteriaQuery.distinct(true)
|
||||
}
|
||||
return predicateSet
|
||||
@ -310,9 +302,8 @@ class HibernateQueryCriteriaParser(val contractType: Class<out ContractState>,
|
||||
// deal participants
|
||||
criteria.participants?.let {
|
||||
val participants = criteria.participants as List<AbstractParty>
|
||||
val joinLinearStateToParty = vaultLinearStates.join<VaultSchemaV1.VaultLinearStates, CommonSchemaV1.Party>("participants")
|
||||
val participantKeys = participants.map { it.nameOrNull().toString() }
|
||||
predicateSet.add(criteriaBuilder.and(joinLinearStateToParty.get<CommonSchemaV1.Party>("name").`in`(participantKeys)))
|
||||
val joinLinearStateToParty = vaultLinearStates.joinSet<VaultSchemaV1.VaultLinearStates, AbstractParty>("participants")
|
||||
predicateSet.add(criteriaBuilder.and(joinLinearStateToParty.`in`(participants)))
|
||||
criteriaQuery.distinct(true)
|
||||
}
|
||||
return predicateSet
|
||||
|
@ -119,7 +119,14 @@ class HibernateVaultQueryImpl(hibernateConfig: HibernateConfiguration,
|
||||
val vaultState = result[0] as VaultSchemaV1.VaultStates
|
||||
val stateRef = StateRef(SecureHash.parse(vaultState.stateRef!!.txId!!), vaultState.stateRef!!.index!!)
|
||||
val state = vaultState.contractState.deserialize<TransactionState<T>>(context = STORAGE_CONTEXT)
|
||||
statesMeta.add(Vault.StateMetadata(stateRef, vaultState.contractStateClassName, vaultState.recordedTime, vaultState.consumedTime, vaultState.stateStatus, vaultState.notaryName, vaultState.notaryKey, vaultState.lockId, vaultState.lockUpdateTime))
|
||||
statesMeta.add(Vault.StateMetadata(stateRef,
|
||||
vaultState.contractStateClassName,
|
||||
vaultState.recordedTime,
|
||||
vaultState.consumedTime,
|
||||
vaultState.stateStatus,
|
||||
vaultState.notary,
|
||||
vaultState.lockId,
|
||||
vaultState.lockUpdateTime))
|
||||
statesAndRefs.add(StateAndRef(state, stateRef))
|
||||
}
|
||||
else {
|
||||
|
@ -98,7 +98,6 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
|
||||
contractStateClassName = it.value.state.data.javaClass.name
|
||||
contractState = it.value.state.serialize(context = STORAGE_CONTEXT).bytes
|
||||
notaryName = it.value.state.notary.name.toString()
|
||||
notaryKey = it.value.state.notary.owningKey.toBase58String()
|
||||
recordedTime = services.clock.instant()
|
||||
}
|
||||
insert(state)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.corda.node.services.vault
|
||||
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.schemas.CommonSchemaV1
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.schemas.PersistentState
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -22,17 +22,14 @@ object VaultSchema
|
||||
*/
|
||||
@CordaSerializable
|
||||
object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, version = 1,
|
||||
mappedTypes = listOf(VaultStates::class.java, VaultLinearStates::class.java, VaultFungibleStates::class.java, CommonSchemaV1.Party::class.java)) {
|
||||
mappedTypes = listOf(VaultStates::class.java, VaultLinearStates::class.java, VaultFungibleStates::class.java)) {
|
||||
@Entity
|
||||
@Table(name = "vault_states",
|
||||
indexes = arrayOf(Index(name = "state_status_idx", columnList = "state_status")))
|
||||
class VaultStates(
|
||||
/** refers to the notary a state is attached to */
|
||||
/** refers to the X500Name of the notary a state is attached to */
|
||||
@Column(name = "notary_name")
|
||||
var notaryName: String,
|
||||
|
||||
@Column(name = "notary_key", length = 65535) // TODO What is the upper limit on size of CompositeKey?
|
||||
var notaryKey: String,
|
||||
var notary: AbstractParty,
|
||||
|
||||
/** references a concrete ContractState that is [QueryableState] and has a [MappedSchema] */
|
||||
@Column(name = "contract_state_class_name")
|
||||
@ -71,8 +68,13 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
|
||||
Index(name = "uuid_index", columnList = "uuid")))
|
||||
class VaultLinearStates(
|
||||
/** [ContractState] attributes */
|
||||
@OneToMany(cascade = arrayOf(CascadeType.ALL))
|
||||
var participants: Set<CommonSchemaV1.Party>,
|
||||
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
@Column(name = "participants")
|
||||
var participants: MutableSet<AbstractParty>? = null,
|
||||
// Reason for not using Set is described here:
|
||||
// https://stackoverflow.com/questions/44213074/kotlin-collection-has-neither-generic-type-or-onetomany-targetentity
|
||||
|
||||
/**
|
||||
* Represents a [LinearState] [UniqueIdentifier]
|
||||
@ -86,18 +88,23 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
|
||||
constructor(uid: UniqueIdentifier, _participants: List<AbstractParty>) :
|
||||
this(externalId = uid.externalId,
|
||||
uuid = uid.id,
|
||||
participants = _participants.map{ CommonSchemaV1.Party(it) }.toSet() )
|
||||
participants = _participants.toMutableSet())
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "vault_fungible_states")
|
||||
class VaultFungibleStates(
|
||||
/** [ContractState] attributes */
|
||||
@OneToMany(cascade = arrayOf(CascadeType.ALL))
|
||||
var participants: Set<CommonSchemaV1.Party>,
|
||||
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
@Column(name = "participants")
|
||||
var participants: MutableSet<AbstractParty>? = null,
|
||||
|
||||
/** [OwnableState] attributes */
|
||||
@Column(name = "owner_id")
|
||||
|
||||
/** X500Name of owner party **/
|
||||
@Column(name = "owner_name")
|
||||
var owner: AbstractParty,
|
||||
|
||||
/** [FungibleAsset] attributes
|
||||
@ -111,8 +118,10 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
|
||||
var quantity: Long,
|
||||
|
||||
/** Issuer attributes */
|
||||
@OneToOne(cascade = arrayOf(CascadeType.ALL))
|
||||
var issuerParty: CommonSchemaV1.Party,
|
||||
|
||||
/** X500Name of issuer party **/
|
||||
@Column(name = "issuer_name")
|
||||
var issuer: AbstractParty,
|
||||
|
||||
@Column(name = "issuer_reference")
|
||||
var issuerRef: ByteArray
|
||||
@ -120,8 +129,8 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
|
||||
constructor(_owner: AbstractParty, _quantity: Long, _issuerParty: AbstractParty, _issuerRef: OpaqueBytes, _participants: List<AbstractParty>) :
|
||||
this(owner = _owner,
|
||||
quantity = _quantity,
|
||||
issuerParty = CommonSchemaV1.Party(_issuerParty),
|
||||
issuer = _issuerParty,
|
||||
issuerRef = _issuerRef.bytes,
|
||||
participants = _participants.map { CommonSchemaV1.Party(it) }.toSet())
|
||||
participants = _participants.toMutableSet())
|
||||
}
|
||||
}
|
@ -8,9 +8,7 @@ import net.corda.core.contracts.*;
|
||||
import net.corda.core.crypto.EncodingUtils;
|
||||
import net.corda.core.identity.AbstractParty;
|
||||
import net.corda.core.messaging.DataFeed;
|
||||
import net.corda.core.node.services.Vault;
|
||||
import net.corda.core.node.services.VaultQueryException;
|
||||
import net.corda.core.node.services.VaultQueryService;
|
||||
import net.corda.core.node.services.*;
|
||||
import net.corda.core.node.services.vault.*;
|
||||
import net.corda.core.node.services.vault.QueryCriteria.LinearStateQueryCriteria;
|
||||
import net.corda.core.node.services.vault.QueryCriteria.VaultCustomQueryCriteria;
|
||||
@ -44,6 +42,7 @@ import static net.corda.core.utilities.ByteArrays.toHexString;
|
||||
import static net.corda.testing.CoreTestUtils.*;
|
||||
import static net.corda.testing.TestConstants.*;
|
||||
import static net.corda.testing.node.MockServicesKt.makeTestDatabaseAndMockServices;
|
||||
import static net.corda.testing.node.MockServicesKt.makeTestIdentityService;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class VaultQueryJavaTests extends TestDependencyInjectionBase {
|
||||
@ -58,7 +57,9 @@ public class VaultQueryJavaTests extends TestDependencyInjectionBase {
|
||||
ArrayList<KeyPair> keys = new ArrayList<>();
|
||||
keys.add(getMEGA_CORP_KEY());
|
||||
keys.add(getDUMMY_NOTARY_KEY());
|
||||
Pair<CordaPersistence, MockServices> databaseAndServices = makeTestDatabaseAndMockServices(Collections.EMPTY_SET, keys);
|
||||
|
||||
IdentityService identitySvc = makeTestIdentityService();
|
||||
Pair<CordaPersistence, MockServices> databaseAndServices = makeTestDatabaseAndMockServices(Collections.EMPTY_SET, keys, () -> identitySvc);
|
||||
issuerServices = new MockServices(getDUMMY_CASH_ISSUER_KEY(), getBOC_KEY());
|
||||
database = databaseAndServices.getFirst();
|
||||
services = databaseAndServices.getSecond();
|
||||
|
@ -641,9 +641,8 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
|
||||
// search predicate
|
||||
val cashStatesSchema = criteriaQuery.from(SampleCashSchemaV3.PersistentCashState::class.java)
|
||||
|
||||
val joinCashToParty = cashStatesSchema.join<SampleCashSchemaV3.PersistentCashState, CommonSchemaV1.Party>("owner")
|
||||
val queryOwnerKey = BOB_PUBKEY.toBase58String()
|
||||
criteriaQuery.where(criteriaBuilder.equal(joinCashToParty.get<CommonSchemaV1.Party>("key"), queryOwnerKey))
|
||||
val queryOwner = BOB.name.toString()
|
||||
criteriaQuery.where(criteriaBuilder.equal(cashStatesSchema.get<String>("owner"), queryOwner))
|
||||
|
||||
val joinVaultStatesToCash = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), cashStatesSchema.get<PersistentStateRef>("stateRef"))
|
||||
criteriaQuery.where(joinVaultStatesToCash)
|
||||
@ -726,9 +725,9 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
|
||||
// search predicate
|
||||
val cashStatesSchema = criteriaQuery.from(SampleCashSchemaV3.PersistentCashState::class.java)
|
||||
|
||||
val joinCashToParty = cashStatesSchema.join<SampleCashSchemaV3.PersistentCashState, CommonSchemaV1.Party>("participants")
|
||||
val queryParticipantKeys = firstCashState.state.data.participants.map { it.owningKey.toBase58String() }
|
||||
criteriaQuery.where(criteriaBuilder.equal(joinCashToParty.get<CommonSchemaV1.Party>("key"), queryParticipantKeys))
|
||||
val queryParticipants = firstCashState.state.data.participants.map { it.nameOrNull().toString() }
|
||||
val joinCashStateToParty = cashStatesSchema.joinSet<SampleCashSchemaV3.PersistentCashState, String>("participants")
|
||||
criteriaQuery.where(criteriaBuilder.and(joinCashStateToParty.`in`(queryParticipants)))
|
||||
|
||||
val joinVaultStatesToCash = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), cashStatesSchema.get<PersistentStateRef>("stateRef"))
|
||||
criteriaQuery.where(joinVaultStatesToCash)
|
||||
|
@ -174,7 +174,6 @@ class RequeryConfigurationTest : TestDependencyInjectionBase() {
|
||||
contractStateClassName = DummyContract.SingleOwnerState::class.java.name
|
||||
contractState = DummyContract.SingleOwnerState(owner = AnonymousParty(MEGA_CORP_PUBKEY)).serialize().bytes
|
||||
notaryName = txn.tx.notary!!.name.toString()
|
||||
notaryKey = txn.tx.notary!!.owningKey.toBase58String()
|
||||
recordedTime = Instant.now()
|
||||
}
|
||||
return state
|
||||
|
@ -69,11 +69,11 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
lockId: UUID = UUID.randomUUID(),
|
||||
withIssuerRefs: Set<OpaqueBytes>? = null): List<StateAndRef<Cash.State>> {
|
||||
|
||||
val notaryName = if (notary != null) listOf(notary.name) else null
|
||||
var baseCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notaryName = notaryName)
|
||||
val notaries = if (notary != null) listOf(notary) else null
|
||||
var baseCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = notaries)
|
||||
if (onlyFromIssuerParties != null || withIssuerRefs != null) {
|
||||
baseCriteria = baseCriteria.and(QueryCriteria.FungibleAssetQueryCriteria(
|
||||
issuerPartyName = onlyFromIssuerParties?.toList(),
|
||||
issuer = onlyFromIssuerParties?.toList(),
|
||||
issuerRef = withIssuerRefs?.toList()))
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.entropyToKeyPair
|
||||
import net.corda.core.crypto.toBase58String
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.services.*
|
||||
import net.corda.core.node.services.vault.*
|
||||
import net.corda.core.node.services.vault.QueryCriteria.*
|
||||
@ -50,11 +51,20 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
lateinit var notaryServices: MockServices
|
||||
val vaultSvc: VaultService get() = services.vaultService
|
||||
val vaultQuerySvc: VaultQueryService get() = services.vaultQueryService
|
||||
val identitySvc: IdentityService = makeTestIdentityService()
|
||||
lateinit var database: CordaPersistence
|
||||
|
||||
// test cash notary
|
||||
val CASH_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(21)) }
|
||||
val CASH_NOTARY: Party get() = Party(X500Name("CN=Cash Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), CASH_NOTARY_KEY.public)
|
||||
val CASH_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CASH_NOTARY.nameOrNull()!!, CASH_NOTARY_KEY.public)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY))
|
||||
// register additional identities
|
||||
identitySvc.verifyAndRegisterIdentity(CASH_NOTARY_IDENTITY)
|
||||
identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY)
|
||||
val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), identitySvc = { identitySvc })
|
||||
database = databaseAndServices.first
|
||||
services = databaseAndServices.second
|
||||
notaryServices = MockServices(DUMMY_NOTARY_KEY, DUMMY_CASH_ISSUER_KEY, BOC_KEY, MEGA_CORP_KEY)
|
||||
@ -71,7 +81,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Ignore
|
||||
@Test
|
||||
fun createPersistentTestDb() {
|
||||
val database = configureDatabase(makePersistentDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = ::makeTestIdentityService)
|
||||
val database = configureDatabase(makePersistentDataSourceProperties(), makeTestDatabaseProperties(), identitySvc = { identitySvc })
|
||||
|
||||
setUpDb(database, 5000)
|
||||
|
||||
@ -396,9 +406,6 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
}
|
||||
}
|
||||
|
||||
val CASH_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(21)) }
|
||||
val CASH_NOTARY: Party get() = Party(X500Name("CN=Cash Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), CASH_NOTARY_KEY.public)
|
||||
|
||||
@Test
|
||||
fun `unconsumed states by notary`() {
|
||||
database.transaction {
|
||||
@ -408,7 +415,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
services.fillWithSomeTestDeals(listOf("123", "456", "789"))
|
||||
|
||||
// DOCSTART VaultQueryExample4
|
||||
val criteria = VaultQueryCriteria(notaryName = listOf(CASH_NOTARY.name))
|
||||
val criteria = VaultQueryCriteria(notary = listOf(CASH_NOTARY))
|
||||
val results = vaultQuerySvc.queryBy<ContractState>(criteria)
|
||||
// DOCEND VaultQueryExample4
|
||||
assertThat(results.states).hasSize(3)
|
||||
@ -418,6 +425,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `unconsumed linear states for single participant`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
services.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
|
||||
@ -433,13 +441,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `unconsumed linear states for two participants`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
services.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
|
||||
services.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP))
|
||||
services.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(MEGA_CORP))
|
||||
|
||||
// DOCSTART VaultQueryExample5
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP))
|
||||
val results = vaultQuerySvc.queryBy<ContractState>(criteria)
|
||||
// DOCEND VaultQueryExample5
|
||||
|
||||
@ -793,6 +802,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `aggregate functions sum by issuer and currency and sort by aggregate sum`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = DUMMY_CASH_ISSUER)
|
||||
services.fillWithSomeTestCash(200.DOLLARS, notaryServices, DUMMY_NOTARY, 2, 2, Random(0L), issuedBy = BOC.ref(1))
|
||||
@ -1026,6 +1036,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 100, 100, Random(0L))
|
||||
|
||||
@Suppress("OVERFLOW_EXPECTED")
|
||||
val pagingSpec = PageSpecification(DEFAULT_PAGE_NUM, MAX_PAGE_SIZE + 1) // overflow = -2147483648
|
||||
val criteria = VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
vaultQuerySvc.queryBy<ContractState>(criteria, paging = pagingSpec)
|
||||
@ -1375,7 +1386,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
|
||||
database.transaction {
|
||||
|
||||
val parties = listOf(MEGA_CORP)
|
||||
val parties = listOf(MINI_CORP)
|
||||
|
||||
services.fillWithSomeTestLinearStates(2, "TEST")
|
||||
services.fillWithSomeTestDeals(listOf("456"), parties)
|
||||
@ -1395,13 +1406,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `unconsumed fungible assets for specific issuer party and refs`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)), ref = OpaqueBytes.of(1))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(2)), ref = OpaqueBytes.of(2))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(3)), ref = OpaqueBytes.of(3))
|
||||
|
||||
val criteria = FungibleAssetQueryCriteria(issuerPartyName = listOf(BOC),
|
||||
val criteria = FungibleAssetQueryCriteria(issuer = listOf(BOC),
|
||||
issuerRef = listOf(BOC.ref(1).reference, BOC.ref(2).reference))
|
||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(criteria)
|
||||
assertThat(results.states).hasSize(2)
|
||||
@ -1424,11 +1436,12 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
val chfCashIssuerServices = MockServices(chfCashIssuerKey)
|
||||
|
||||
database.transaction {
|
||||
|
||||
services.fillWithSomeTestCash(100.POUNDS, gbpCashIssuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (gbpCashIssuer))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, usdCashIssuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (usdCashIssuer))
|
||||
services.fillWithSomeTestCash(100.SWISS_FRANCS, chfCashIssuerServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (chfCashIssuer))
|
||||
|
||||
val criteria = FungibleAssetQueryCriteria(issuerPartyName = listOf(gbpCashIssuer.party, usdCashIssuer.party))
|
||||
val criteria = FungibleAssetQueryCriteria(issuer = listOf(gbpCashIssuer.party, usdCashIssuer.party))
|
||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(criteria)
|
||||
assertThat(results.states).hasSize(2)
|
||||
}
|
||||
@ -1438,17 +1451,16 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
fun `unconsumed fungible assets by owner`() {
|
||||
database.transaction {
|
||||
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 2, 2, Random(0L), issuedBy = BOC.ref(1))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = BOC.ref(1))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L),
|
||||
issuedBy = MEGA_CORP.ref(0), ownedBy = (MEGA_CORP))
|
||||
issuedBy = MEGA_CORP.ref(0), ownedBy = (MINI_CORP))
|
||||
|
||||
val criteria = FungibleAssetQueryCriteria(owner = listOf(MEGA_CORP))
|
||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(criteria)
|
||||
assertThat(results.states).hasSize(1)
|
||||
assertThat(results.states).hasSize(1) // can only be 1 owner of a node (MEGA_CORP in this MockServices setup)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `unconsumed fungible states for owners`() {
|
||||
database.transaction {
|
||||
@ -1464,7 +1476,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
val results = vaultQuerySvc.queryBy<ContractState>(criteria)
|
||||
// DOCEND VaultQueryExample5.2
|
||||
|
||||
assertThat(results.states).hasSize(1) // can only be 1 owner of a node (MEGA_CORP in this MockServices setup)
|
||||
assertThat(results.states).hasSize(2) // can only be 1 owner of a node (MEGA_CORP in this MockServices setup)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1555,12 +1567,13 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `unconsumed fungible assets for issuer party`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BOC_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (DUMMY_CASH_ISSUER))
|
||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L), issuedBy = (BOC.ref(1)))
|
||||
|
||||
// DOCSTART VaultQueryExample14
|
||||
val criteria = FungibleAssetQueryCriteria(issuerPartyName = listOf(BOC))
|
||||
val criteria = FungibleAssetQueryCriteria(issuer = listOf(BOC))
|
||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(criteria)
|
||||
// DOCEND VaultQueryExample14
|
||||
|
||||
@ -1823,6 +1836,41 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unconsumed linear heads for single participant`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||
services.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE))
|
||||
services.fillWithSomeTestLinearStates(1)
|
||||
services.fillWithSomeTestLinearStates(1, "TEST3")
|
||||
|
||||
val linearStateCriteria = LinearStateQueryCriteria(participants = listOf(ALICE))
|
||||
val results = vaultQuerySvc.queryBy<LinearState>(linearStateCriteria)
|
||||
|
||||
assertThat(results.states).hasSize(1)
|
||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unconsumed linear heads for multiple participants`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||
identitySvc.verifyAndRegisterIdentity(CHARLIE_IDENTITY)
|
||||
|
||||
services.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE,BOB,CHARLIE))
|
||||
services.fillWithSomeTestLinearStates(1)
|
||||
services.fillWithSomeTestLinearStates(1, "TEST3")
|
||||
|
||||
val linearStateCriteria = LinearStateQueryCriteria(participants = listOf(ALICE,BOB,CHARLIE))
|
||||
val results = vaultQuerySvc.queryBy<LinearState>(linearStateCriteria)
|
||||
|
||||
assertThat(results.states).hasSize(1)
|
||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unconsumed linear heads where external id is null`() {
|
||||
database.transaction {
|
||||
|
@ -5,6 +5,7 @@ package net.corda.testing
|
||||
|
||||
import com.nhaarman.mockito_kotlin.spy
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.contracts.asset.DUMMY_CASH_ISSUER
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.identity.Party
|
||||
@ -88,7 +89,9 @@ val BIG_CORP_PARTY_REF = BIG_CORP.ref(OpaqueBytes.of(1)).reference
|
||||
|
||||
val ALL_TEST_KEYS: List<KeyPair> get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY)
|
||||
|
||||
val MOCK_IDENTITIES = listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_NOTARY_IDENTITY)
|
||||
val DUMMY_CASH_ISSUER_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_CASH_ISSUER.party as Party)
|
||||
|
||||
val MOCK_IDENTITIES = listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)
|
||||
val MOCK_IDENTITY_SERVICE: IdentityService get() = InMemoryIdentityService(MOCK_IDENTITIES, emptySet(), DUMMY_CA.certificate.cert)
|
||||
|
||||
val MOCK_HOST_AND_PORT = NetworkHostAndPort("mockHost", 30000)
|
||||
|
@ -61,6 +61,7 @@ val BOB: Party get() = Party(X500Name("CN=Bob Plc,O=Bob Plc,L=Rome,C=IT"), BOB_K
|
||||
|
||||
val CHARLIE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(90)) }
|
||||
/** Dummy individual identity for tests and simulations */
|
||||
val CHARLIE_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CHARLIE)
|
||||
val CHARLIE: Party get() = Party(X500Name("CN=Charlie Ltd,O=Charlie Ltd,L=Athens,C=GR"), CHARLIE_KEY.public)
|
||||
|
||||
val DUMMY_REGULATOR_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(100)) }
|
||||
|
@ -42,6 +42,7 @@ class DummyDealContract : Contract {
|
||||
override fun generateMappedObject(schema: MappedSchema): PersistentState {
|
||||
return when (schema) {
|
||||
is DummyDealStateSchemaV1 -> DummyDealStateSchemaV1.PersistentDummyDealState(
|
||||
_participants = participants.toSet(),
|
||||
uid = linearId
|
||||
)
|
||||
else -> throw IllegalArgumentException("Unrecognised schema $schema")
|
||||
|
@ -50,6 +50,7 @@ class DummyLinearContract : Contract {
|
||||
override fun generateMappedObject(schema: MappedSchema): PersistentState {
|
||||
return when (schema) {
|
||||
is DummyLinearStateSchemaV1 -> DummyLinearStateSchemaV1.PersistentDummyLinearState(
|
||||
participants = participants.toMutableSet(),
|
||||
externalId = linearId.externalId,
|
||||
uuid = linearId.id,
|
||||
linearString = linearString,
|
||||
@ -58,6 +59,7 @@ class DummyLinearContract : Contract {
|
||||
linearBoolean = linearBoolean
|
||||
)
|
||||
is DummyLinearStateSchemaV2 -> DummyLinearStateSchemaV2.PersistentDummyLinearState(
|
||||
_participants = participants.toSet(),
|
||||
uid = linearId,
|
||||
linearString = linearString,
|
||||
linearNumber = linearNumber,
|
||||
|
@ -119,14 +119,14 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
|
||||
issuedBy: PartyAndReference = DUMMY_CASH_ISSUER): Vault<Cash.State> {
|
||||
val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng)
|
||||
|
||||
val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey
|
||||
val me = AnonymousParty(myKey)
|
||||
val myKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey
|
||||
val anonParty = AnonymousParty(myKey)
|
||||
|
||||
// We will allocate one state to one transaction, for simplicities sake.
|
||||
val cash = Cash()
|
||||
val transactions: List<SignedTransaction> = amounts.map { pennies ->
|
||||
val issuance = TransactionBuilder(null as Party?)
|
||||
cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary)
|
||||
cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), anonParty, outputNotary)
|
||||
|
||||
return@map issuerServices.signInitialTransaction(issuance, issuedBy.party.owningKey)
|
||||
}
|
||||
|
@ -217,13 +217,15 @@ fun makeTestDatabaseProperties(): Properties {
|
||||
|
||||
fun makeTestIdentityService() = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DUMMY_CA.certificate)
|
||||
|
||||
fun makeTestDatabaseAndMockServices(customSchemas: Set<MappedSchema> = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1, CashSchemaV1), keys: List<KeyPair> = listOf(MEGA_CORP_KEY)): Pair<CordaPersistence, MockServices> {
|
||||
fun makeTestDatabaseAndMockServices(customSchemas: Set<MappedSchema> = setOf(CommercialPaperSchemaV1, DummyLinearStateSchemaV1, CashSchemaV1),
|
||||
keys: List<KeyPair> = listOf(MEGA_CORP_KEY),
|
||||
identitySvc: ()-> IdentityService = { makeTestIdentityService() }): Pair<CordaPersistence, MockServices> {
|
||||
val dataSourceProps = makeTestDataSourceProperties()
|
||||
val databaseProperties = makeTestDatabaseProperties()
|
||||
|
||||
val database = configureDatabase(dataSourceProps, databaseProperties, identitySvc = ::makeTestIdentityService)
|
||||
val database = configureDatabase(dataSourceProps, databaseProperties, identitySvc = identitySvc)
|
||||
val mockService = database.transaction {
|
||||
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), databaseProperties, identitySvc = ::makeTestIdentityService)
|
||||
val hibernateConfig = HibernateConfiguration(NodeSchemaService(customSchemas), databaseProperties, identitySvc = identitySvc)
|
||||
object : MockServices(*(keys.toTypedArray())) {
|
||||
override val vaultService: VaultService = makeVaultService(dataSourceProps, hibernateConfig)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.testing.schemas
|
||||
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.schemas.CommonSchemaV1
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import javax.persistence.Entity
|
||||
@ -21,8 +22,11 @@ object DummyDealStateSchemaV1 : MappedSchema(schemaFamily = DummyDealStateSchema
|
||||
@Table(name = "dummy_deal_states")
|
||||
class PersistentDummyDealState(
|
||||
/** parent attributes */
|
||||
@Transient
|
||||
val _participants: Set<AbstractParty>,
|
||||
|
||||
@Transient
|
||||
val uid: UniqueIdentifier
|
||||
|
||||
) : CommonSchemaV1.LinearState(uid = uid)
|
||||
) : CommonSchemaV1.LinearState(uid, _participants)
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package net.corda.testing.schemas
|
||||
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.schemas.PersistentState
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.Index
|
||||
import javax.persistence.Table
|
||||
import javax.persistence.*
|
||||
|
||||
/**
|
||||
* An object used to fully qualify the [DummyLinearStateSchema] family name (i.e. independent of version).
|
||||
@ -24,6 +23,12 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc
|
||||
indexes = arrayOf(Index(name = "external_id_idx", columnList = "external_id"),
|
||||
Index(name = "uuid_idx", columnList = "uuid")))
|
||||
class PersistentDummyLinearState(
|
||||
/** [ContractState] attributes */
|
||||
|
||||
/** X500Name of participant parties **/
|
||||
@ElementCollection
|
||||
var participants: MutableSet<AbstractParty>,
|
||||
|
||||
/**
|
||||
* UniqueIdentifier
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.testing.schemas
|
||||
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.schemas.CommonSchemaV1
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import javax.persistence.Column
|
||||
@ -25,7 +26,10 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc
|
||||
@Column(name = "linear_boolean") var linearBoolean: Boolean,
|
||||
|
||||
/** parent attributes */
|
||||
@Transient
|
||||
val _participants: Set<AbstractParty>,
|
||||
|
||||
@Transient
|
||||
val uid: UniqueIdentifier
|
||||
) : CommonSchemaV1.LinearState(uid = uid)
|
||||
) : CommonSchemaV1.LinearState(uid, _participants)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user