Skip to content

Commit

Permalink
Merge pull request #37 from Luxoft/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
seniorjoinu authored Nov 21, 2018
2 parents b271f56 + 2cb35fd commit ef5e7f6
Show file tree
Hide file tree
Showing 52 changed files with 1,910 additions and 1,314 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ using [CreateSchemaFlow](cordapp/README.md#flows):
listOf("NAME", "BORN"))).resultFuture.get()

Ministry creates a [credential definition](cordapp/README.md#indy-terminology) for the shopping scheme
using [CreateClaimDefFlow](cordapp/README.md#flows):
using [CreateCredentialDefinitionFlow](cordapp/README.md#flows):

val credDefId = ministry.services.startFlow(
CreateClaimDefFlow.Authority(schemaId)).resultFuture.get()
val credentialDefinitionId = ministry.services.startFlow(
CreateCredentialDefinitionFlow.Authority(schemaId)).resultFuture.get()

Ministry verifies Alice's legal status and issues her a shopping [credential](cordapp/README.md#indy-terminology)
using [IssueClaimFlow](cordapp/README.md#flows):
using [IssueCredentialFlow](cordapp/README.md#flows):

val credentialProposal = """
{
Expand All @@ -69,21 +69,21 @@ using [IssueClaimFlow](cordapp/README.md#flows):
"""

ministry.services.startFlow(
IssueClaimFlow.Issuer(
IssueCredentialFlow.Issuer(
UUID.randomUUID().toString(),
credDefId,
credentialDefinitionId,
credentialProposal,
aliceX500)).resultFuture.get()

When Alice comes to grocery store, the store asks Alice to verify that she is legally allowed to buy drinks
using [VerifyClaimFlow](cordapp/README.md#flows):
using [VerifyCredentialFlow](cordapp/README.md#flows):

// Alice.BORN >= currentYear - 18
val eighteenYearsAgo = LocalDateTime.now().minusYears(18).year
val legalAgePredicate = VerifyClaimFlow.ProofPredicate(schemaId, credDefId, ministryDID, "BORN", eighteenYearsAgo)
val legalAgePredicate = VerifyCredentialFlow.ProofPredicate(schemaId, credentialDefinitionId, ministryDID, "BORN", eighteenYearsAgo)

val verified = store.services.startFlow(
VerifyClaimFlow.Verifier(
VerifyCredentialFlow.Verifier(
UUID.randomUUID().toString(),
emptyList(),
listOf(legalAgePredicate),
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ task deployNodes(type: net.corda.plugins.Cordform, group: "corda") {

node {
name "O=Issuer,L=London,C=GB"
notary = [validating : true]
notary = [validating: true]
p2pPort 10001
rpcSettings {
address("localhost:10002")
Expand Down Expand Up @@ -103,7 +103,7 @@ task deployNodes(type: net.corda.plugins.Cordform, group: "corda") {
adminAddress("localhost:10203")
}
cordapps = []
rpcUsers = [[user: "user1", "password": "test", "permissions": [ "ALL" ]]]
rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]
}

}
Expand Down
14 changes: 12 additions & 2 deletions cordapp-contracts-states/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ Corda contract and state classes for the [indy-cordapp](../cordapp/README.md) pr

## States

- [IndyClaim](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndyClaim.kt) - A record of an issued Indy claim
- [IndyCredential](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndyCredential.kt) - A record of an issued Indy credential

- [IndyClaimProof](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndyClaimProof.kt) - A record of an issued Indy proof
- [IndyCredentialProof](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndyCredentialProof.kt) - A record of an issued Indy proof

- [IndySchema](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndySchema.kt) - A credential schema from. Each credential should be made from such schema.

- [IndyCredentialDefinition](src/main/kotlin/com/luxoft/blockchainlab/corda/hyperledger/indy/data/state/IndyCredentialDefinition.kt) - It encapsulates credential definition and revocation registry definition.

In Indy world you should create this entities in the next order: Schema -> Credential Definition -> Revocation Registry.
If you are trying to store it in ledger, you should do it in the same order.

Every [IndySchema] can have multiple [IndyCredentialDefinition]s (and also revocation registries) associated with it.
Issuer can issue multiple identical [IndyCredential] with a single [IndyCredentialDefinition] to a single prover.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.luxoft.blockchainlab.corda.hyperledger.indy.contract

import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyClaimProof
import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredentialProof
import com.luxoft.blockchainlab.hyperledger.indy.IndyUser
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
Expand All @@ -11,7 +11,7 @@ import net.corda.core.transactions.LedgerTransaction
import java.security.PublicKey

/**
* Example contract with claim verification. Use responsibly
* Example contract with credential verification. Use responsibly
* as Corda will probably remove JNI support (i.e. Libindy calls)
* in near future in deterministic JVM
*/
Expand All @@ -34,39 +34,44 @@ class IndyCredentialContract : Contract {
}

private fun revocation(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
// TODO: should contain 1 input state of type IndyClaim
// TODO: should contain 1 input state of type IndyCredential
}

private fun verification(tx: LedgerTransaction, signers: Set<PublicKey>, expectedAttrs: List<ExpectedAttr>) = requireThat {
private fun verification(tx: LedgerTransaction, signers: Set<PublicKey>, expectedAttrs: List<ExpectedAttr>) =
requireThat {

"No inputs should be consumed when creating the proof." using (tx.inputStates.isEmpty())
"Only one Proof should be created per verification session." using (tx.outputStates.size == 1)
"No inputs should be consumed when creating the proof." using (tx.inputStates.isEmpty())
"Only one Proof should be created per verification session." using (tx.outputStates.size == 1)

val indyProof = tx.outputsOfType<IndyClaimProof>().singleOrNull()
val indyProof = tx.outputsOfType<IndyCredentialProof>().singleOrNull()
?: throw IllegalArgumentException("Invalid type of output")

"All of the participants must be signers." using (signers.containsAll(indyProof.participants.map { it.owningKey }))
"All of the participants must be signers." using (signers.containsAll(indyProof.participants.map { it.owningKey }))

// TODO: this is unnecessary, 'cause only the caller VerifyProofFlow is interested in proof validity
// TODO: removing this line will make cordentity compatible with sandboxed JVM
"IndyClaim should be verified." using (IndyUser.verifyProof(indyProof.proofReq, indyProof.proof, indyProof.usedData))
// TODO: this is unnecessary, 'cause only the caller VerifyProofFlow is interested in proof validity
// TODO: removing this line will make cordentity compatible with sandboxed JVM
"IndyCredential should be verified." using (IndyUser.verifyProof(
indyProof.proofReq,
indyProof.proof,
indyProof.usedData
))

expectedAttrs.forEach {
"Proof provided for invalid value." using indyProof.proof.isAttributeExists(it.value)
expectedAttrs.forEach {
"Proof provided for invalid value." using indyProof.proof.isAttributeExists(it.value)
}
}
}

private fun creation(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
// TODO: should contain 1 input and 1 output states of type IndyClaimDefinition
// TODO: should contain 1 output state of type IndyClaim
// TODO: should contain 1 input and 1 output states of type IndyCredentialDefinition
// TODO: should contain 1 output state of type IndyCredential
}

@CordaSerializable
data class ExpectedAttr(val name: String, val value: String)

interface Command : CommandData {
class Issue: TypeOnlyCommandData(), Command
class Issue : TypeOnlyCommandData(), Command
data class Verify(val expectedAttrs: List<ExpectedAttr>) : Command
class Revoke: TypeOnlyCommandData(), Command
class Revoke : TypeOnlyCommandData(), Command
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import java.security.PublicKey

class IndyCredentialDefinitionContract : Contract {
override fun verify(tx: LedgerTransaction) {
val incomingCommands = tx.filterCommands<Command> {true}
val incomingCommands = tx.filterCommands<Command> { true }

for (incomingCommand in incomingCommands) {
val signers = incomingCommand.signers.toSet()
Expand All @@ -26,19 +26,19 @@ class IndyCredentialDefinitionContract : Contract {
}

private fun upgrade(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
// TODO: should contain 1 input and 1 output states of type IndyClaimDefinition (different)
// TODO: should contain 1 input and 1 output states of type IndyCredentialDefinition (different)
// TODO: should contain 1 input and 1 output states of type IndySchema (similar)
// TODO: input state of type IndyClaimDefinition should have currentCredNumber == maxCredNumber
// TODO: input state of type IndyCredentialDefinition should have currentCredNumber == maxCredNumber
}

private fun creation(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
// TODO: should contain 1 input and 1 output states of type IndySchema (similar)
// TODO: should contain 1 output state of type IndyClaimDefinition
// TODO: state of type IndyClaimDefinition should have currentCredNumber == 0 and maxCredNumber > 0
// TODO: should contain 1 output state of type IndyCredentialDefinition
// TODO: state of type IndyCredentialDefinition should have currentCredNumber == 0 and maxCredNumber > 0
}

private fun consummation(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
// TODO: should contain 1 input and 1 output states of type IndyClaimDefinition (different)
// TODO: should contain 1 input and 1 output states of type IndyCredentialDefinition (different)
// TODO: input and output state should be similar except output.currentCredNumber - input.currentCredNumber == 1
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.luxoft.blockchainlab.corda.hyperledger.indy.data.schema

import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredentialDefinition
import com.luxoft.blockchainlab.hyperledger.indy.IndyUser
import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import javax.persistence.Column
import javax.persistence.Entity


object CredentialDefinitionSchema

object CredentialDefinitionSchemaV1 : MappedSchema(
version = 1,
schemaFamily = CredentialDefinitionSchema.javaClass,
mappedTypes = listOf(PersistentCredentialDefinition::class.java)
) {
@Entity
data class PersistentCredentialDefinition(
@Column(name = "id") val credentialDefId: String = "",
val schemaId: String = "",
val revRegId: String = "",
val currentCredNumber: Int = 0

) : PersistentState() {
constructor(credentialDef: IndyCredentialDefinition) : this(
credentialDef.credentialDefinitionId.toString(),
credentialDef.schemaId.toString(),
credentialDef.credentialDefinitionId.getRevocationRegistryDefinitionId(IndyUser.REVOCATION_TAG).toString(),
credentialDef.currentCredNumber
)
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
package com.luxoft.blockchainlab.corda.hyperledger.indy.data.schema

import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyClaimProof
import com.luxoft.blockchainlab.corda.hyperledger.indy.data.state.IndyCredentialProof
import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Table


object ClaimProofSchema
object CredentialProofSchema

object ClaimProofSchemaV1 : MappedSchema(
version = 1,
schemaFamily = ClaimProofSchema.javaClass,
mappedTypes = listOf(PersistentProof::class.java)) {
object CredentialProofSchemaV1 : MappedSchema(
version = 1,
schemaFamily = CredentialProofSchema.javaClass,
mappedTypes = listOf(PersistentProof::class.java)
) {

@Entity
@Table(name = "proofs")
class PersistentProof(
@Column(name = "id")
val id: String
@Column(name = "id")
val id: String
) : PersistentState() {
constructor(indyProof: IndyClaimProof): this(indyProof.id)
constructor(): this("")
constructor(indyProof: IndyCredentialProof) : this(indyProof.id)
constructor() : this("")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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

object CredentialSchema

object CredentialSchemaV1 : MappedSchema(
version = 1,
schemaFamily = CredentialSchema.javaClass,
mappedTypes = listOf(PersistentCredential::class.java)
) {

@Entity
@Table(name = "credentials")
class PersistentCredential(
@Column(name = "id")
var id: String,
@Column(name = "issuerDid")
var issuerDid: String

) : PersistentState() {
constructor(indyCredential: IndyCredential) : this(indyCredential.id, indyCredential.issuerDid)
constructor() : this("", "")
}
}
Loading

0 comments on commit ef5e7f6

Please sign in to comment.