Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get rid of credential id #36

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.luxoft.blockchainlab.corda.hyperledger.indy.data.schema
import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredential
import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Table

Expand All @@ -18,13 +17,11 @@ object CredentialSchemaV1 : MappedSchema(
@Entity
@Table(name = "credentials")
class PersistentCredential(
@Column(name = "id")
var id: String,
@Column(name = "issuerDid")
var issuerDid: String
var issuerDid: String,
var proverDid: String

) : PersistentState() {
constructor(indyCredential: IndyCredential) : this(indyCredential.id, indyCredential.issuerDid)
constructor(indyCredential: IndyCredential) : this(indyCredential.issuerDid, indyCredential.proverDid)
constructor() : this("", "")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.QueryableState

/**
* A Corda record of an Indy Credential [credential] issued on request [credentialRequest]
* A Corda record of an Indy Credential issued on request [CredentialRequestInfo]
*
* @param id credential persistent id
* @param credentialRequestInfo indy credential request
* @param credentialInfo indy credential
* @param issuerDid did of an entity issued credential
* @param proverDid did of an entity received credential
* @param participants corda participants
*/
open class IndyCredential(
val id: String,
val credentialRequestInfo: CredentialRequestInfo,
val credentialInfo: CredentialInfo,
val issuerDid: String,
val proverDid: String,
override val participants: List<AbstractParty>
) : LinearState, QueryableState {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import net.corda.core.contracts.StateAndRef
import net.corda.core.flows.FlowLogic
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.vaultQueryBy
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.Builder.equal
Expand All @@ -40,18 +42,59 @@ fun FlowLogic<Any>.indyUser(): IndyUser {
/**
* This method is used to get indy credential state from vault
*
* @param id id of credential
* @param proverDid Did of the receiver
*
* @return corda state of indy credential or null if none exists
*/
fun FlowLogic<Any>.getIndyCredentialState(id: String): StateAndRef<IndyCredential>? {
fun FlowLogic<Any>.getIndyCredentialsByProver(proverDid: String): List<StateAndRef<IndyCredential>> {
val generalCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val existingId = QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::id.equal(id))
val existingId =
QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::proverDid.equal(proverDid))

val criteria = generalCriteria.and(existingId)
val result = serviceHub.vaultService.queryBy<IndyCredential>(criteria)

return result.states.firstOrNull()
return result.states
}

/**
* This method is used to get indy credential state from vault
*
* @param issuerDid Did of the issuer
*
* @return corda state of indy credential or null if none exists
*/
fun FlowLogic<Any>.getIndyCredentialsByIssuer(issuerDid: String): List<StateAndRef<IndyCredential>> {
val generalCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val existingId =
QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::issuerDid.equal(issuerDid))

val criteria = generalCriteria.and(existingId)
val result = serviceHub.vaultService.queryBy<IndyCredential>(criteria)

return result.states
}

fun CordaRPCOps.getIndyCredentialsByIssuer(issuerDid: String): List<StateAndRef<IndyCredential>> {
val generalCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val existingId =
QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::issuerDid.equal(issuerDid))

val criteria = generalCriteria.and(existingId)
val result = vaultQueryBy<IndyCredential>(criteria)

return result.states
}

fun CordaRPCOps.getIndyCredentialsByProver(proverDid: String): List<StateAndRef<IndyCredential>> {
val generalCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val existingId =
QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::proverDid.equal(proverDid))

val criteria = generalCriteria.and(existingId)
val result = vaultQueryBy<IndyCredential>(criteria)

return result.states
}

private fun FlowLogic<Any>.getUnconsumedCredentialDefinitionByCriteria(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ object IssueCredentialFlow {
/**
* A flow to issue an Indy credential based on proposal [credProposal]
*
* [identifier] must be unique for the given Indy user to allow searching Credentials by `(identifier, issuerDID)`
*
* @param identifier new unique ID for the new credential.
* Must be unique for the given Indy user to allow searching Credentials by `(identifier, issuerDID)`
*
* @param credentialDefinitionId id of the credential definition to create new statement (credential)
* @param credentialProposal credential JSON containing attribute values for each of requested attribute names.
* Example:
Expand All @@ -48,7 +43,6 @@ object IssueCredentialFlow {
@InitiatingFlow
@StartableByRPC
open class Issuer(
private val identifier: String,
private val credentialProposal: String,
private val credentialDefinitionId: CredentialDefinitionId,
private val proverName: CordaX500Name
Expand Down Expand Up @@ -88,10 +82,10 @@ object IssueCredentialFlow {
offer
)
val credentialOut = IndyCredential(
identifier,
credentialReq,
credential,
indyUser().did,
credentialReq.request.proverDid,
listOf(ourIdentity, prover)
)
StateAndContract(credentialOut, IndyCredentialContract::class.java.name)
Expand Down Expand Up @@ -138,13 +132,10 @@ object IssueCredentialFlow {
@Suspendable
override fun call() {
try {
val issuer = flowSession.counterparty.name

val offer = flowSession.receive<CredentialOffer>().unwrap { offer -> offer }
val sessionDid = subFlow(CreatePairwiseFlow.Prover(issuer))

val credentialRequestInfo =
indyUser().createCredentialRequest(sessionDid, offer, indyUser().defaultMasterSecretId)
indyUser().createCredentialRequest(indyUser().did, offer, indyUser().defaultMasterSecretId)
flowSession.send(credentialRequestInfo)

val flow = object : SignTransactionFlow(flowSession) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package com.luxoft.blockchainlab.corda.hyperledger.indy.flow

import co.paralleluniverse.fibers.Suspendable
import com.luxoft.blockchainlab.corda.hyperledger.indy.contract.IndyCredentialContract
import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredential
import com.luxoft.blockchainlab.hyperledger.indy.getRevocationRegistryId
import net.corda.core.contracts.Command
import net.corda.core.contracts.StateAndRef
import net.corda.core.flows.*
import net.corda.core.transactions.TransactionBuilder

Expand All @@ -14,19 +16,15 @@ import net.corda.core.transactions.TransactionBuilder
object RevokeCredentialFlow {

/**
* @param id credential id generated by [issueCredentialFlow]
* @param credentialStateIn credential generated by [IssueCredentialFlow]
*/
@InitiatingFlow
@StartableByRPC
open class Issuer(private val id: String) : FlowLogic<Unit>() {
open class Issuer(private val credentialStateIn: StateAndRef<IndyCredential>) : FlowLogic<Unit>() {

@Suspendable
override fun call() {
try {
// query vault for credential with id = credential id
val credentialStateIn = getIndyCredentialState(id)
?: throw RuntimeException("No such credential in vault")

val credential = credentialStateIn.state.data

val revRegId = credential.credentialInfo.credential.getRevocationRegistryId()!!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package com.luxoft.blockchainlab.corda.hyperledger.indy


import com.luxoft.blockchainlab.corda.hyperledger.indy.data.schema.CredentialSchemaV1
import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredential
import com.luxoft.blockchainlab.corda.hyperledger.indy.flow.*
import com.luxoft.blockchainlab.hyperledger.indy.CredentialDefinitionId
import com.luxoft.blockchainlab.hyperledger.indy.Interval
import com.luxoft.blockchainlab.hyperledger.indy.SchemaId
import net.corda.core.contracts.StateAndRef
import net.corda.core.identity.CordaX500Name
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.Builder.equal
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode
import net.corda.node.services.api.VaultServiceInternal
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
Expand Down Expand Up @@ -63,30 +71,24 @@ class CordentityE2E : CordaTestBase() {
credentialIssuer: StartedNode<MockNode>,
credentialProposal: String,
credentialDefId: CredentialDefinitionId
): String {

val identifier = UUID.randomUUID().toString()

) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How am I supposed to reference the issued credential if I don't have its ID? Could you document it in a doc-comment for this method?

val credentialFuture = credentialIssuer.services.startFlow(
IssueCredentialFlow.Issuer(
identifier,
credentialProposal,
credentialDefId,
credentialProver.getName()
)
).resultFuture

credentialFuture.getOrThrow(Duration.ofSeconds(30))

return identifier
}

private fun revokeCredential(
issuer: StartedNode<MockNode>,
credentialId: String
credentialStateIn: StateAndRef<IndyCredential>
) {
val flowResult = issuer.services.startFlow(
RevokeCredentialFlow.Issuer(credentialId)
RevokeCredentialFlow.Issuer(credentialStateIn)
).resultFuture

flowResult.getOrThrow(Duration.ofSeconds(30))
Expand Down Expand Up @@ -274,8 +276,7 @@ class CordentityE2E : CordaTestBase() {
val schemaAttrInt = "1988"
val credentialProposal = schemaPerson.formatProposal("John Smith", "119191919", schemaAttrInt, schemaAttrInt)

val credentialId =
issueCredential(alice, issuer, credentialProposal, credentialDefinitionId)
issueCredential(alice, issuer, credentialProposal, credentialDefinitionId)

// Verify credential
val attributes = listOf(
Expand All @@ -300,7 +301,12 @@ class CordentityE2E : CordaTestBase() {
val credentialVerified = verifyCredential(bob, alice, attributes, predicates, Interval.allTime())
assertTrue(credentialVerified)

revokeCredential(issuer, credentialId)
val states = issuer.database.transaction {
issuer.services.vaultService.getIndyCredentialsByProver(alice.getPartyDid())
}
assert(states.size == 1) { "Invalid claims count" }

revokeCredential(issuer, states.first())

Thread.sleep(3000)

Expand Down Expand Up @@ -435,4 +441,15 @@ class CordentityE2E : CordaTestBase() {
val credentialVerified = verifyCredential(bob, alice, attributes, emptyList(), Interval.allTime())
assertTrue(credentialVerified)
}
}

fun VaultServiceInternal.getIndyCredentialsByProver(proverDid: String): List<StateAndRef<IndyCredential>> {
val generalCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val existingId =
QueryCriteria.VaultCustomQueryCriteria(CredentialSchemaV1.PersistentCredential::proverDid.equal(proverDid))

val criteria = generalCriteria.and(existingId)
val result = queryBy<IndyCredential>(criteria)

return result.states
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class ReadmeExampleTest : CordaTestBase() {

ministry.services.startFlow(
IssueCredentialFlow.Issuer(
UUID.randomUUID().toString(),
credentialProposal,
credentialDefinitionId,
aliceX500
Expand Down