diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7f6e192 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +max_line_length = 140 \ No newline at end of file diff --git a/build.gradle b/build.gradle index f964538..d82ca5b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { corda_artifactory_url = 'https://software.r3.com/artifactory' corda_group = 'net.corda' - corda_release_version = '4.8' + corda_release_version = '4.9' corda_gradle_plugin_group = 'net.corda.plugins' corda_gradle_plugin_version = '5.0.4' @@ -14,10 +14,10 @@ buildscript { junit_version = '5.3.1' onixlabs_group = 'io.onixlabs' - onixlabs_corda_core_release_version = '4.0.0-rc3' - onixlabs_corda_idfx_release_version = '4.0.0-rc5' + onixlabs_corda_core_release_version = '4.0.1' + onixlabs_corda_idfx_release_version = '4.0.1' - cordapp_platform_version = 10 + cordapp_platform_version = 11 cordapp_contract_name = 'ONIXLabs Corda BNMS Contract' cordapp_workflow_name = 'ONIXLabs Corda BNMS Workflow' cordapp_vendor_name = 'ONIXLabs' diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/ConfigurationBuilder.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/ConfigurationBuilder.kt index da282d3..803bb54 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/ConfigurationBuilder.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/ConfigurationBuilder.kt @@ -196,7 +196,7 @@ class ConfigurationBuilder(private val settings: MutableSet>) { * * @return Returns a configuration containing the settings built by this configuration builder. */ - fun toConfiguration(): Configuration { + internal fun toConfiguration(): Configuration { return Configuration(settings) } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/Membership.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/Membership.kt index 4cf35b6..7df2b1a 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/Membership.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/Membership.kt @@ -92,17 +92,7 @@ data class Membership( * @return Returns a persistent state entity. */ override fun generateMappedObject(schema: MappedSchema): PersistentState = when (schema) { - is MembershipSchemaV1 -> MembershipEntity( - linearId = linearId.id, - externalId = linearId.externalId, - holder = holder, - networkValue = network.value, - normalizedNetworkValue = network.normalizedValue, - networkOperator = network.operator, - networkHash = network.hash.toString(), - isNetworkOperator = isNetworkOperator, - hash = hash.toString() - ) + is MembershipSchemaV1 -> MembershipEntity(this) else -> throw IllegalArgumentException("Unrecognised schema: $schema.") } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestation.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestation.kt index 1abd068..073d814 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestation.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestation.kt @@ -68,6 +68,19 @@ class MembershipAttestation internal constructor( previousStateRef ), NetworkState { + /** + * Represents a membership attestation; a proof that a particular [Membership] state has been witnessed. + * + * @param attestor The party who is attesting to the witnessed [Membership] state. + * @param membership The [Membership] state that is being witnessed and attested. + * @param status The status of the attestation. + * @param metadata Additional information about the attestation. + * @param linearId The unique identifier of the attestation. + * @param previousStateRef The state reference of the previous state in the chain. + * + * The primary constructor of the [MembershipAttestation] class is deliberately private + * to enforce static attestation pointers via the secondary constructor. + */ constructor( attestor: AbstractParty, membership: StateAndRef, @@ -79,7 +92,7 @@ class MembershipAttestation internal constructor( membership.state.data.network, attestor, setOf(membership.state.data.holder), - membership.toStaticAttestationPointer(identifier = membership.state.data.linearId.toString()), + membership.toStaticAttestationPointer(), status, metadata, linearId, @@ -126,22 +139,7 @@ class MembershipAttestation internal constructor( * @return Returns a persistent state entity. */ override fun generateMappedObject(schema: MappedSchema): PersistentState = when (schema) { - is MembershipAttestationSchemaV1 -> MembershipAttestationEntity( - linearId = linearId.id, - externalId = linearId.externalId, - attestor = attestor, - holder = holder, - networkValue = network.value, - normalizedNetworkValue = network.normalizedValue, - networkOperator = network.operator, - networkHash = network.hash.toString(), - pointer = pointer.statePointer.toString(), - pointerStateType = pointer.stateType.canonicalName, - pointerHash = pointer.hash.toString(), - status = status, - previousStateRef = previousStateRef?.toString(), - hash = hash.toString() - ) + is MembershipAttestationSchemaV1 -> MembershipAttestationEntity(this) else -> super.generateMappedObject(schema) } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestationSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestationSchema.kt index f5e52a9..34fbbd1 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestationSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipAttestationSchema.kt @@ -76,5 +76,22 @@ object MembershipAttestationSchema { @Column(name = "hash", nullable = false, unique = true) val hash: String = "" - ) : PersistentState() + ) : PersistentState() { + constructor(attestation: MembershipAttestation) : this( + linearId = attestation.linearId.id, + externalId = attestation.linearId.externalId, + attestor = attestation.attestor, + holder = attestation.holder, + networkValue = attestation.network.value, + normalizedNetworkValue = attestation.network.normalizedValue, + networkOperator = attestation.network.operator, + networkHash = attestation.network.hash.toString(), + pointer = attestation.pointer.statePointer.toString(), + pointerStateType = attestation.pointer.stateType.canonicalName, + pointerHash = attestation.pointer.hash.toString(), + status = attestation.status, + previousStateRef = attestation.previousStateRef?.toString(), + hash = attestation.hash.toString() + ) + } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipSchema.kt index 8fdb4a5..001db0d 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/membership/MembershipSchema.kt @@ -61,5 +61,17 @@ object MembershipSchema { @Column(name = "hash", nullable = false, unique = true) val hash: String = "" - ) : PersistentState() + ) : PersistentState() { + constructor(membership: Membership) : this( + linearId = membership.linearId.id, + externalId = membership.linearId.externalId, + holder = membership.holder, + networkValue = membership.network.value, + normalizedNetworkValue = membership.network.normalizedValue, + networkOperator = membership.network.operator, + networkHash = membership.network.hash.toString(), + isNetworkOperator = membership.isNetworkOperator, + hash = membership.hash.toString() + ) + } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/Relationship.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/Relationship.kt index e675720..e7edba4 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/Relationship.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/Relationship.kt @@ -94,15 +94,7 @@ data class Relationship( * @return Returns a persistent state entity. */ override fun generateMappedObject(schema: MappedSchema): PersistentState = when (schema) { - is RelationshipSchemaV1 -> RelationshipEntity( - linearId = linearId.id, - externalId = linearId.externalId, - networkValue = network.value, - normalizedNetworkValue = network.normalizedValue, - networkOperator = network.operator, - networkHash = network.hash.toString(), - hash = hash.toString() - ) + is RelationshipSchemaV1 -> RelationshipEntity(this) else -> throw IllegalArgumentException("Unrecognised schema: $schema.") } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestation.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestation.kt index 1ce9029..791d673 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestation.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestation.kt @@ -18,6 +18,7 @@ package io.onixlabs.corda.bnms.contract.relationship import io.onixlabs.corda.bnms.contract.Network import io.onixlabs.corda.bnms.contract.NetworkState +import io.onixlabs.corda.bnms.contract.membership.Membership import io.onixlabs.corda.bnms.contract.relationship.RelationshipAttestationSchema.RelationshipAttestationEntity import io.onixlabs.corda.bnms.contract.relationship.RelationshipAttestationSchema.RelationshipAttestationSchemaV1 import io.onixlabs.corda.identityframework.contract.attestations.Attestation @@ -32,6 +33,20 @@ import net.corda.core.identity.AbstractParty import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.PersistentState +/** + * Represents a relationship attestation; a proof that a particular [Relationship] state has been witnessed. + * + * @property network The business network that this relationship attestation belongs to. + * @property attestor The party who is attesting to the witnessed [Relationship] state. + * @property attestees The parties of this attestation, usually the participants of the attested [Relationship] state. + * @property pointer The pointer to the attested [Relationship] state. + * @property status The status of the attestation. + * @property metadata Additional information about the attestation. + * @property linearId The unique identifier of the attestation. + * @property previousStateRef The state reference of the previous state in the chain. + * @property hash The unique hash which represents this attestation. + * @property participants The participants of this attestation; namely the attestor and attestees. + */ @BelongsToContract(RelationshipAttestationContract::class) class RelationshipAttestation internal constructor( override val network: Network, @@ -89,21 +104,7 @@ class RelationshipAttestation internal constructor( } override fun generateMappedObject(schema: MappedSchema): PersistentState = when (schema) { - is RelationshipAttestationSchemaV1 -> RelationshipAttestationEntity( - linearId = linearId.id, - externalId = linearId.externalId, - attestor = attestor, - networkValue = network.value, - normalizedNetworkValue = network.normalizedValue, - networkOperator = network.operator, - networkHash = network.hash.toString(), - pointer = pointer.statePointer.toString(), - pointerStateType = pointer.stateType.canonicalName, - pointerHash = pointer.hash.toString(), - status = status, - previousStateRef = previousStateRef?.toString(), - hash = hash.toString() - ) + is RelationshipAttestationSchemaV1 -> RelationshipAttestationEntity(this) else -> super.generateMappedObject(schema) } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestationSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestationSchema.kt index fb1a616..1ecf507 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestationSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipAttestationSchema.kt @@ -73,5 +73,21 @@ object RelationshipAttestationSchema { @Column(name = "hash", nullable = false, unique = true) val hash: String = "" - ) : PersistentState() + ) : PersistentState() { + constructor(attestation: RelationshipAttestation) : this( + linearId = attestation.linearId.id, + externalId = attestation.linearId.externalId, + attestor = attestation.attestor, + networkValue = attestation.network.value, + normalizedNetworkValue = attestation.network.normalizedValue, + networkOperator = attestation.network.operator, + networkHash = attestation.network.hash.toString(), + pointer = attestation.pointer.statePointer.toString(), + pointerStateType = attestation.pointer.stateType.canonicalName, + pointerHash = attestation.pointer.hash.toString(), + status = attestation.status, + previousStateRef = attestation.previousStateRef?.toString(), + hash = attestation.hash.toString() + ) + } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfiguration.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfiguration.kt index 85496e9..f8017e4 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfiguration.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfiguration.kt @@ -57,17 +57,7 @@ class RelationshipConfiguration private constructor( get() = SecureHash.sha256("${configuration.hash}$relationshipLinearId") override fun generateMappedObject(schema: MappedSchema) = when (schema) { - is RelationshipConfigurationSchemaV1 -> RelationshipConfigurationEntity( - linearId = linearId.id, - externalId = linearId.externalId, - relationshipLinearId = relationshipLinearId.id, - relationshipExternalId = relationshipLinearId.externalId, - networkValue = network.value, - networkOperator = network.operator, - networkHash = network.hash.toString(), - configurationHash = configuration.hash.toString(), - hash = hash.toString() - ) + is RelationshipConfigurationSchemaV1 -> RelationshipConfigurationEntity(this) else -> throw IllegalArgumentException("Unrecognised schema: $schema.") } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfigurationSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfigurationSchema.kt index d4f696c..2f315b0 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfigurationSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipConfigurationSchema.kt @@ -49,6 +49,9 @@ object RelationshipConfigurationSchema { @Column(name = "network_value", nullable = false) val networkValue: String = "", + @Column(name = "normalized_network_value", nullable = false) + val normalizedNetworkValue: String = "", + @Column(name = "network_operator", nullable = true) val networkOperator: AbstractParty? = null, @@ -60,5 +63,18 @@ object RelationshipConfigurationSchema { @Column(name = "hash", nullable = false) val hash: String = "" - ) : PersistentState() + ) : PersistentState() { + constructor(configuration: RelationshipConfiguration) : this( + linearId = configuration.linearId.id, + externalId = configuration.linearId.externalId, + relationshipLinearId = configuration.relationshipLinearId.id, + relationshipExternalId = configuration.relationshipLinearId.externalId, + networkValue = configuration.network.value, + normalizedNetworkValue = configuration.network.normalizedValue, + networkOperator = configuration.network.operator, + networkHash = configuration.network.hash.toString(), + configurationHash = configuration.configuration.hash.toString(), + hash = configuration.hash.toString() + ) + } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipSchema.kt index 2735d11..f50f8d0 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/relationship/RelationshipSchema.kt @@ -54,5 +54,15 @@ object RelationshipSchema { @Column(name = "hash", nullable = false, unique = true) val hash: String = "" - ) : PersistentState() + ) : PersistentState() { + constructor(relationship: Relationship) : this( + linearId = relationship.linearId.id, + externalId = relationship.linearId.externalId, + networkValue = relationship.network.value, + normalizedNetworkValue = relationship.network.normalizedValue, + networkOperator = relationship.network.operator, + networkHash = relationship.network.hash.toString(), + hash = relationship.hash.toString() + ) + } } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLock.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLock.kt index 54b3e57..d44689d 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLock.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLock.kt @@ -40,12 +40,7 @@ data class RevocationLock( } override fun generateMappedObject(schema: MappedSchema): PersistentState = when (schema) { - is RevocationLockSchemaV1 -> RevocationLockEntity( - owner = owner, - pointerStateLinearId = pointer.pointer.id, - pointerStateExternalId = pointer.pointer.externalId, - pointerStateClass = pointer.type.canonicalName - ) + is RevocationLockSchemaV1 -> RevocationLockEntity(this) else -> throw IllegalArgumentException("Unrecognised schema: $schema.") } diff --git a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLockSchema.kt b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLockSchema.kt index e3826c6..f3612ac 100644 --- a/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLockSchema.kt +++ b/onixlabs-corda-bnms-contract/src/main/kotlin/io/onixlabs/corda/bnms/contract/revocation/RevocationLockSchema.kt @@ -46,5 +46,12 @@ object RevocationLockSchema { @Column(name = "pointer_state_class", nullable = false) val pointerStateClass: String = "" - ) : PersistentState() -} \ No newline at end of file + ) : PersistentState() { + constructor(revocationLock: RevocationLock<*>) : this( + owner = revocationLock.owner, + pointerStateLinearId = revocationLock.pointer.pointer.id, + pointerStateExternalId = revocationLock.pointer.pointer.externalId, + pointerStateClass = revocationLock.pointer.type.canonicalName + ) + } +} diff --git a/onixlabs-corda-bnms-contract/src/main/resources/migration/relationship-configuration-schema.changelog-v1.xml b/onixlabs-corda-bnms-contract/src/main/resources/migration/relationship-configuration-schema.changelog-v1.xml index 4bf0c7f..3a0b79a 100644 --- a/onixlabs-corda-bnms-contract/src/main/resources/migration/relationship-configuration-schema.changelog-v1.xml +++ b/onixlabs-corda-bnms-contract/src/main/resources/migration/relationship-configuration-schema.changelog-v1.xml @@ -21,6 +21,9 @@ + + + @@ -36,4 +39,4 @@ constraintName="PK_relationship_configuration_states" tableName="relationship_configuration_states"/> - \ No newline at end of file + diff --git a/onixlabs-corda-bnms-contract/src/test/kotlin/io/onixlabs/corda/bnms/contract/ContractTest.kt b/onixlabs-corda-bnms-contract/src/test/kotlin/io/onixlabs/corda/bnms/contract/ContractTest.kt index cb8f6f5..be4dbf9 100644 --- a/onixlabs-corda-bnms-contract/src/test/kotlin/io/onixlabs/corda/bnms/contract/ContractTest.kt +++ b/onixlabs-corda-bnms-contract/src/test/kotlin/io/onixlabs/corda/bnms/contract/ContractTest.kt @@ -55,7 +55,7 @@ abstract class ContractTest { @BeforeEach private fun setup() { val networkParameters = testNetworkParameters( - minimumPlatformVersion = 5, + minimumPlatformVersion = 11, notaries = listOf(NotaryInfo(TestIdentity(DUMMY_NOTARY_NAME, 20).party, true)) ) _services = MockServices(cordapps, IDENTITY_A, networkParameters, IDENTITY_B, IDENTITY_C) diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.FlowLogic.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.FlowLogic.kt index 259eb96..defeaa0 100644 --- a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.FlowLogic.kt +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.FlowLogic.kt @@ -19,14 +19,10 @@ package io.onixlabs.corda.bnms.workflow import co.paralleluniverse.fibers.Suspendable import io.onixlabs.corda.bnms.contract.membership.Membership import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation -import io.onixlabs.corda.bnms.contract.membership.MembershipAttestationSchema.MembershipAttestationEntity -import io.onixlabs.corda.bnms.contract.membership.MembershipSchema.MembershipEntity import io.onixlabs.corda.bnms.contract.relationship.Relationship import io.onixlabs.corda.bnms.contract.relationship.RelationshipAttestation import io.onixlabs.corda.bnms.contract.revocation.RevocationLock -import io.onixlabs.corda.bnms.contract.revocation.RevocationLockSchema.RevocationLockEntity import io.onixlabs.corda.core.services.any -import io.onixlabs.corda.core.services.equalTo import io.onixlabs.corda.core.services.singleOrNull import io.onixlabs.corda.core.services.vaultServiceFor import io.onixlabs.corda.core.workflow.currentStep @@ -54,18 +50,43 @@ fun FlowLogic<*>.checkMembershipHandler(session: FlowSession): Boolean { @Suspendable fun FlowLogic<*>.checkMembershipExists(membership: Membership) { - val membershipExists = serviceHub.vaultServiceFor().any { + val existingMembership = serviceHub.vaultServiceFor().singleOrNull { stateStatus(Vault.StateStatus.ALL) - expression(MembershipEntity::hash equalTo membership.hash.toString()) + membershipHash(membership.hash) } - if (membershipExists) { - throw FlowException("Membership state with the specified unique hash already exists: ${membership.hash}.") + if (existingMembership != null) { + throw FlowException("The specified membership already exists: ${existingMembership.state.data}.") } } @Suspendable -fun FlowLogic<*>.checkMembershipsAndAttestations(relationship: Relationship) { +fun FlowLogic<*>.checkMembershipAttestationExistsForIssuance(attestation: MembershipAttestation) { + val existingAttestation = serviceHub.vaultServiceFor().singleOrNull { + membershipAttestationAttestor(attestation.attestor) + membershipAttestationHolder(attestation.holder) + membershipAttestationNetworkHash(attestation.network.hash) + } + + if (existingAttestation != null) { + throw FlowException("The specified membership attestation already exists and should be amended: ${existingAttestation.state.data}.") + } +} + +@Suspendable +fun FlowLogic<*>.checkMembershipAttestationExistsForAmendment(attestation: MembershipAttestation) { + val existingAttestation = serviceHub.vaultServiceFor().singleOrNull { + stateStatus(Vault.StateStatus.ALL) + membershipAttestationHash(attestation.hash) + } + + if (existingAttestation != null) { + throw FlowException("The specified membership attestation already exists: ${existingAttestation.state.data}.") + } +} + +@Suspendable +fun FlowLogic<*>.checkMembershipsAndAttestations(relationship: Relationship, ourAttestorIdentity: AbstractParty = ourIdentity) { currentStep(CheckMembershipStep) val counterparties = relationship.participants .map { serviceHub.identityService.requireWellKnownPartyFromAnonymous(it) } @@ -73,19 +94,22 @@ fun FlowLogic<*>.checkMembershipsAndAttestations(relationship: Relationship) { counterparties.forEach { val membership = serviceHub.vaultServiceFor().singleOrNull { - expression(MembershipEntity::holder equalTo it) - expression(MembershipEntity::networkHash equalTo relationship.network.hash.toString()) + membershipHolder(it) + membershipNetworkHash(relationship.network.hash) } ?: throw FlowException(buildString { - append("Membership for '$it' on network '${relationship.network}' ") - append("could not be found, or has not been witnessed by this node.") + append("Membership with the specified details could not be found, or has not been witnessed by this node: ") + append("Holder = $it, ") + append("Network = ${relationship.network}.") }) serviceHub.vaultServiceFor().singleOrNull { - expression(MembershipAttestationEntity::attestor equalTo ourIdentity) - expression(MembershipAttestationEntity::pointer equalTo membership.ref.toString()) + membershipAttestationAttestor(ourAttestorIdentity) + membershipAttestationPointer(membership.ref) } ?: throw FlowException(buildString { - append("MembershipAttestation for '${membership.state.data.holder}' ") - append("could not be found, or has not been witnessed by this node.") + append("Membership attestation with the specified details could not be found, or has not been witnessed by this node: ") + append("Holder = ${membership.state.data.holder}, ") + append("Attestor = $ourAttestorIdentity, ") + append("Network = ${membership.state.data.network}.") }) } } @@ -93,9 +117,9 @@ fun FlowLogic<*>.checkMembershipsAndAttestations(relationship: Relationship) { @Suspendable fun FlowLogic<*>.checkRevocationLockExists(owner: AbstractParty, state: LinearState) { val revocationLockExists = serviceHub.vaultServiceFor>().any { - expression(RevocationLockEntity::owner equalTo owner) - expression(RevocationLockEntity::pointerStateClass equalTo state.javaClass.canonicalName) - expression(RevocationLockEntity::pointerStateLinearId equalTo state.linearId.id) + revocationLockOwner(owner) + revocationLockPointerStateClass(state.javaClass) + revocationLockPointerStateLinearId(state.linearId.id) } if (revocationLockExists) { @@ -105,14 +129,17 @@ fun FlowLogic<*>.checkRevocationLockExists(owner: AbstractParty, state: LinearSt @Suspendable fun FlowLogic<*>.findMembershipForAttestation(attestation: MembershipAttestation): StateAndRef { - return attestation.pointer.resolve(serviceHub) ?: throw FlowException( - "Membership for the specified attestation could not be found, or has not been witnessed by this node." - ) + return attestation.pointer.resolve(serviceHub) ?: throw FlowException(buildString { + append("Membership with the specified details could not be found, or has not been witnessed by this node: ") + append("Holder = ${attestation.holder}, ") + append("Network = ${attestation.network}.") + }) } @Suspendable fun FlowLogic<*>.findRelationshipForAttestation(attestation: RelationshipAttestation): StateAndRef { - return attestation.pointer.resolve(serviceHub) ?: throw FlowException( - "Relationship for the specified attestation could not be found, or has not been witnessed by this node." - ) + return attestation.pointer.resolve(serviceHub) ?: throw FlowException(buildString { + append("Relationship with the specified details could not be found, or has not been witnessed by this node: ") + append("Network = ${attestation.network}.") + }) } diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Membership.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Membership.kt new file mode 100644 index 0000000..0acae10 --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Membership.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.membership.Membership +import io.onixlabs.corda.bnms.contract.membership.MembershipSchema.MembershipEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty + +@QueryDslContext +fun QueryDsl.membershipHolder(value: AbstractParty) { + expression(MembershipEntity::holder equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipNetworkValue(value: String) { + expression(MembershipEntity::networkValue equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipNormalizedNetworkValue(value: String) { + expression(MembershipEntity::normalizedNetworkValue equalTo value.toUpperCase()) +} + +@QueryDslContext +fun QueryDsl.membershipNetworkOperator(value: AbstractParty?) { + if (value == null) expression(MembershipEntity::networkOperator.isNull()) + else expression(MembershipEntity::networkOperator equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipNetworkHash(value: SecureHash) { + expression(MembershipEntity::networkHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipIsNetworkOperator(value: Boolean) { + expression(MembershipEntity::isNetworkOperator equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipHash(value: SecureHash) { + expression(MembershipEntity::hash equalTo value.toString()) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.MembershipAttestation.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.MembershipAttestation.kt new file mode 100644 index 0000000..968f03f --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.MembershipAttestation.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation +import io.onixlabs.corda.bnms.contract.membership.MembershipAttestationSchema.MembershipAttestationEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import io.onixlabs.corda.identityframework.contract.attestations.AttestationStatus +import net.corda.core.contracts.ContractState +import net.corda.core.contracts.StateRef +import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty + +@QueryDslContext +fun QueryDsl.membershipAttestationAttestor(value: AbstractParty) { + expression(MembershipAttestationEntity::attestor equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationHolder(value: AbstractParty) { + expression(MembershipAttestationEntity::holder equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationNetworkValue(value: String) { + expression(MembershipAttestationEntity::networkValue equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationNormalizedNetworkValue(value: String) { + expression(MembershipAttestationEntity::normalizedNetworkValue equalTo value.toUpperCase()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationNetworkOperator(value: AbstractParty?) { + if (value == null) expression(MembershipAttestationEntity::networkOperator.isNull()) + else expression(MembershipAttestationEntity::networkOperator equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationNetworkHash(value: SecureHash) { + expression(MembershipAttestationEntity::networkHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationPointer(value: Any) { + expression(MembershipAttestationEntity::pointer equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationPointerStateType(value: Class) { + expression(MembershipAttestationEntity::pointerStateType equalTo value.canonicalName) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationPointerHash(value: SecureHash) { + expression(MembershipAttestationEntity::pointerHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationStatus(value: AttestationStatus) { + expression(MembershipAttestationEntity::status equalTo value) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationPreviousStateRef(value: StateRef?) { + if (value == null) expression(MembershipAttestationEntity::previousStateRef.isNull()) + else expression(MembershipAttestationEntity::previousStateRef equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.membershipAttestationHash(value: SecureHash) { + expression(MembershipAttestationEntity::hash equalTo value.toString()) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Relationship.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Relationship.kt new file mode 100644 index 0000000..b4cfa43 --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.Relationship.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.membership.Membership +import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation +import io.onixlabs.corda.bnms.contract.membership.MembershipAttestationSchema +import io.onixlabs.corda.bnms.contract.relationship.Relationship +import io.onixlabs.corda.bnms.contract.relationship.RelationshipSchema.RelationshipEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import io.onixlabs.corda.identityframework.contract.attestations.AttestationStatus +import net.corda.core.contracts.ContractState +import net.corda.core.contracts.StateRef +import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty + +@QueryDslContext +fun QueryDsl.relationshipNetworkValue(value: String) { + expression(RelationshipEntity::networkValue equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipNormalizedNetworkValue(value: String) { + expression(RelationshipEntity::normalizedNetworkValue equalTo value.toUpperCase()) +} + +@QueryDslContext +fun QueryDsl.relationshipNetworkOperator(value: AbstractParty?) { + if (value == null) expression(RelationshipEntity::networkOperator.isNull()) + else expression(RelationshipEntity::networkOperator equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipNetworkHash(value: SecureHash) { + expression(RelationshipEntity::networkHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipHash(value: SecureHash) { + expression(RelationshipEntity::hash equalTo value.toString()) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipAttestation.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipAttestation.kt new file mode 100644 index 0000000..25e23a1 --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipAttestation.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.relationship.RelationshipAttestation +import io.onixlabs.corda.bnms.contract.relationship.RelationshipAttestationSchema.RelationshipAttestationEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import io.onixlabs.corda.identityframework.contract.attestations.AttestationStatus +import net.corda.core.contracts.ContractState +import net.corda.core.contracts.StateRef +import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty + +@QueryDslContext +fun QueryDsl.relationshipAttestationAttestor(value: AbstractParty) { + expression(RelationshipAttestationEntity::attestor equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationNetworkValue(value: String) { + expression(RelationshipAttestationEntity::networkValue equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationNormalizedNetworkValue(value: String) { + expression(RelationshipAttestationEntity::normalizedNetworkValue equalTo value.toUpperCase()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationNetworkOperator(value: AbstractParty?) { + if (value == null) expression(RelationshipAttestationEntity::networkOperator.isNull()) + else expression(RelationshipAttestationEntity::networkOperator equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationNetworkHash(value: SecureHash) { + expression(RelationshipAttestationEntity::networkHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationPointer(value: Any) { + expression(RelationshipAttestationEntity::pointer equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationPointerStateType(value: Class) { + expression(RelationshipAttestationEntity::pointerStateType equalTo value.canonicalName) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationPointerHash(value: SecureHash) { + expression(RelationshipAttestationEntity::pointerHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationStatus(value: AttestationStatus) { + expression(RelationshipAttestationEntity::status equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationPreviousStateRef(value: StateRef?) { + if (value == null) expression(RelationshipAttestationEntity::previousStateRef.isNull()) + else expression(RelationshipAttestationEntity::previousStateRef equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipAttestationHash(value: SecureHash) { + expression(RelationshipAttestationEntity::hash equalTo value.toString()) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipConfiguration.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipConfiguration.kt new file mode 100644 index 0000000..7bee87a --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RelationshipConfiguration.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.relationship.RelationshipConfiguration +import io.onixlabs.corda.bnms.contract.relationship.RelationshipConfigurationSchema.RelationshipConfigurationEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty +import java.util.* + +@QueryDslContext +fun QueryDsl.relationshipConfigurationRelationshipLinearId(value: UUID) { + expression(RelationshipConfigurationEntity::relationshipLinearId equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationRelationshipExternalId(value: String?) { + if (value == null) expression(RelationshipConfigurationEntity::relationshipExternalId.isNull()) + else expression(RelationshipConfigurationEntity::relationshipExternalId equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationNetworkValue(value: String) { + expression(RelationshipConfigurationEntity::networkValue equalTo value) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationNormalizedNetworkValue(value: String) { + expression(RelationshipConfigurationEntity::normalizedNetworkValue equalTo value.toUpperCase()) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationNetworkOperator(value: AbstractParty?) { + if (value == null) expression(RelationshipConfigurationEntity::networkOperator.isNull()) + else expression(RelationshipConfigurationEntity::networkOperator equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationNormalizedNetworkHash(value: SecureHash) { + expression(RelationshipConfigurationEntity::networkHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationConfigurationHash(value: SecureHash) { + expression(RelationshipConfigurationEntity::configurationHash equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl.relationshipConfigurationHash(value: SecureHash) { + expression(RelationshipConfigurationEntity::hash equalTo value.toString()) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RevocationLock.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RevocationLock.kt new file mode 100644 index 0000000..958b87e --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/Extensions.QueryDsl.RevocationLock.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow + +import io.onixlabs.corda.bnms.contract.revocation.RevocationLock +import io.onixlabs.corda.bnms.contract.revocation.RevocationLockSchema.RevocationLockEntity +import io.onixlabs.corda.core.services.QueryDsl +import io.onixlabs.corda.core.services.QueryDslContext +import io.onixlabs.corda.core.services.equalTo +import io.onixlabs.corda.core.services.isNull +import net.corda.core.contracts.LinearState +import net.corda.core.identity.AbstractParty +import java.util.* + +@QueryDslContext +fun QueryDsl>.revocationLockOwner(value: AbstractParty) { + expression(RevocationLockEntity::owner equalTo value) +} + +@QueryDslContext +fun QueryDsl>.revocationLockPointerStateLinearId(value: UUID) { + expression(RevocationLockEntity::pointerStateLinearId equalTo value) +} + +@QueryDslContext +fun QueryDsl>.pointerStateExternalId(value: String?) { + if (value == null) expression(RevocationLockEntity::pointerStateExternalId.isNull()) + else expression(RevocationLockEntity::pointerStateExternalId equalTo value.toString()) +} + +@QueryDslContext +fun QueryDsl>.revocationLockPointerStateClass(value: Class) { + expression(RevocationLockEntity::pointerStateClass equalTo value.canonicalName) +} diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendMembershipAttestationFlow.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendMembershipAttestationFlow.kt index 37df9e3..0760e59 100644 --- a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendMembershipAttestationFlow.kt +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendMembershipAttestationFlow.kt @@ -19,6 +19,7 @@ package io.onixlabs.corda.bnms.workflow.membership import co.paralleluniverse.fibers.Suspendable import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation import io.onixlabs.corda.bnms.workflow.addAmendedMembershipAttestation +import io.onixlabs.corda.bnms.workflow.checkMembershipAttestationExistsForAmendment import io.onixlabs.corda.bnms.workflow.findMembershipForAttestation import io.onixlabs.corda.core.workflow.* import io.onixlabs.corda.identityframework.workflow.checkAttestationExistsForAmendment @@ -54,7 +55,7 @@ class AmendMembershipAttestationFlow( override fun call(): SignedTransaction { currentStep(InitializeFlowStep) checkSufficientSessionsForContractStates(sessions, newAttestation) - checkAttestationExistsForAmendment(newAttestation) + checkMembershipAttestationExistsForAmendment(newAttestation) val membership = findMembershipForAttestation(newAttestation).referenced() diff --git a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueMembershipAttestationFlow.kt b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueMembershipAttestationFlow.kt index 1d43271..b0f679f 100644 --- a/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueMembershipAttestationFlow.kt +++ b/onixlabs-corda-bnms-workflow/src/main/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueMembershipAttestationFlow.kt @@ -19,6 +19,8 @@ package io.onixlabs.corda.bnms.workflow.membership import co.paralleluniverse.fibers.Suspendable import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation import io.onixlabs.corda.bnms.workflow.addIssuedMembershipAttestation +import io.onixlabs.corda.bnms.workflow.checkMembershipAttestationExistsForAmendment +import io.onixlabs.corda.bnms.workflow.checkMembershipAttestationExistsForIssuance import io.onixlabs.corda.bnms.workflow.findMembershipForAttestation import io.onixlabs.corda.core.workflow.* import io.onixlabs.corda.identityframework.workflow.checkAttestationExistsForIssuance @@ -53,7 +55,7 @@ class IssueMembershipAttestationFlow( override fun call(): SignedTransaction { currentStep(InitializeFlowStep) checkSufficientSessionsForContractStates(sessions, attestation) - checkAttestationExistsForIssuance(attestation) + checkMembershipAttestationExistsForIssuance(attestation) val membership = findMembershipForAttestation(attestation).referenced() diff --git a/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/FlowTest.kt b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/FlowTest.kt index c33769d..df11639 100644 --- a/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/FlowTest.kt +++ b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/FlowTest.kt @@ -79,7 +79,7 @@ abstract class FlowTest { private fun setup() { _network = MockNetwork( MockNetworkParameters( - networkParameters = testNetworkParameters(minimumPlatformVersion = 10), + networkParameters = testNetworkParameters(minimumPlatformVersion = 11), cordappsForAllNodes = listOf( TestCordapp.findCordapp("io.onixlabs.corda.identityframework.contract"), TestCordapp.findCordapp("io.onixlabs.corda.identityframework.workflow"), diff --git a/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendDuplicateMembershipAttestationFlowTests.kt b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendDuplicateMembershipAttestationFlowTests.kt new file mode 100644 index 0000000..798e014 --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/AmendDuplicateMembershipAttestationFlowTests.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow.membership + +import io.onixlabs.corda.bnms.contract.membership.Membership +import io.onixlabs.corda.bnms.contract.membership.MembershipAttestation +import io.onixlabs.corda.bnms.contract.membership.accept +import io.onixlabs.corda.bnms.workflow.FlowTest +import io.onixlabs.corda.bnms.workflow.Pipeline +import net.corda.core.contracts.StateAndRef +import net.corda.core.flows.FlowException +import net.corda.core.transactions.SignedTransaction +import org.junit.jupiter.api.Test +import kotlin.test.assertFailsWith + +class AmendDuplicateMembershipAttestationFlowTests : FlowTest() { + + private lateinit var membership: StateAndRef + private lateinit var oldAttestation: StateAndRef + private lateinit var newAttestation: MembershipAttestation + private lateinit var transaction: SignedTransaction + + override fun initialize() { + Pipeline + .create(network) + .run(nodeA) { + IssueMembershipFlow.Initiator(MEMBERSHIP, observers = setOf(partyB)) + } + .run(nodeB) { + membership = it.tx.outRefsOfType().single() + val attestation = membership.accept(partyB) + IssueMembershipAttestationFlow.Initiator(attestation) + } + .finally { + oldAttestation = it.tx.outRefsOfType().single() + transaction = it + } + } + + @Test + fun `AmendMembershipAttestationFlow should fail because an existing membership attestation already exists`() { + val exception = assertFailsWith { + Pipeline + .create(network) + .run(nodeB) { + newAttestation = oldAttestation.state.data + AmendMembershipAttestationFlow.Initiator(oldAttestation, newAttestation) + } + } + + assert(exception.message!!.startsWith("The specified membership attestation already exists:")) + } +} diff --git a/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueDuplicateMembershipAttestationFlowTests.kt b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueDuplicateMembershipAttestationFlowTests.kt new file mode 100644 index 0000000..55d153e --- /dev/null +++ b/onixlabs-corda-bnms-workflow/src/test/kotlin/io/onixlabs/corda/bnms/workflow/membership/IssueDuplicateMembershipAttestationFlowTests.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2020-2022 ONIXLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.onixlabs.corda.bnms.workflow.membership + +import io.onixlabs.corda.bnms.contract.membership.Membership +import io.onixlabs.corda.bnms.contract.membership.accept +import io.onixlabs.corda.bnms.contract.membership.getNextOutput +import io.onixlabs.corda.bnms.workflow.FlowTest +import io.onixlabs.corda.bnms.workflow.Pipeline +import net.corda.core.contracts.StateAndRef +import net.corda.core.flows.FlowException +import net.corda.core.transactions.SignedTransaction +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class IssueDuplicateMembershipAttestationFlowTests : FlowTest() { + + private lateinit var oldMembership: StateAndRef + private lateinit var newMembership: StateAndRef + private lateinit var transaction: SignedTransaction + + override fun initialize() { + Pipeline + .create(network) + .run(nodeA) { + IssueMembershipFlow.Initiator(MEMBERSHIP, observers = setOf(partyB)) + } + .run(nodeB) { + oldMembership = it.tx.outRefsOfType().single() + val attestation = oldMembership.accept(partyB) + IssueMembershipAttestationFlow.Initiator(attestation) + } + .run(nodeA) { + val membership = oldMembership.getNextOutput().configure { addSetting("Test", "Test") } + AmendMembershipFlow.Initiator(oldMembership, membership, observers = setOf(partyB)) + } + .finally { + newMembership = it.tx.outRefsOfType().single() + transaction = it + } + } + + @Test + fun `IssueMembershipAttestationFlow should fail because an existing membership attestation already exists`() { + val exception = assertFailsWith { + Pipeline + .create(network) + .run(nodeB) { + val attestation = newMembership.accept(partyB) + IssueMembershipAttestationFlow.Initiator(attestation) + } + } + + assert(exception.message!!.startsWith("The specified membership attestation already exists and should be amended:")) + } +}