Skip to content

Commit

Permalink
feat: Create & Store Presentation (#794)
Browse files Browse the repository at this point in the history
Signed-off-by: Bassam Riman <[email protected]>
  • Loading branch information
CryptoKnightIOG authored Nov 22, 2023
1 parent 5376b74 commit 1bf9287
Show file tree
Hide file tree
Showing 24 changed files with 623 additions and 104 deletions.
Binary file modified pollux/lib/anoncreds/anoncreds-jvm-1.0-SNAPSHOT.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
28 changes: 16 additions & 12 deletions pollux/lib/anoncreds/native-lib/helper_script_to_update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@

RELEASES=https://github.com/input-output-hk/anoncreds-rs/releases/download/
VERSION=expose_presentation_methods_in_uniffi
SHA="16a7178ca979f7643788f6ebf8189131ab922a53"
SHA="ea59e64c4e6be3885c3c4907d02d63254e2025c4"

mkdir NATIVE_new
mkdir NATIVE_new/darwin-aarch64
mkdir NATIVE_new/darwin-x86-64
mkdir NATIVE_new/linux-aarch64
mkdir NATIVE_new/linux-x86-64
rm -rf NATIVE/darwin-aarch64
rm -rf NATIVE/darwin-x86-64
rm -rf NATIVE/linux-aarch64
rm -rf NATIVE/linux-x86-64

wget -c $RELEASES/$VERSION/library-darwin-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/darwin-aarch64
wget -c $RELEASES/$VERSION/library-darwin-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/darwin-x86-64
wget -c $RELEASES/$VERSION/library-linux-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/linux-aarch64
wget -c $RELEASES/$VERSION/library-linux-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/linux-x86-64
mkdir NATIVE/darwin-aarch64
mkdir NATIVE/darwin-x86-64
mkdir NATIVE/linux-aarch64
mkdir NATIVE/linux-x86-64

rename 'libanoncreds_uniffi.so' 'libuniffi_anoncreds.so' NATIVE_new/**/*.so
rename 'libanoncreds_uniffi.dylib' 'libuniffi_anoncreds.dylib' NATIVE_new/**/*.dylib
wget -c $RELEASES/$VERSION/library-darwin-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE/darwin-aarch64
wget -c $RELEASES/$VERSION/library-darwin-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE/darwin-x86-64
wget -c $RELEASES/$VERSION/library-linux-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE/linux-aarch64
wget -c $RELEASES/$VERSION/library-linux-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE/linux-x86-64

rename 'libanoncreds_uniffi.so' 'libuniffi_anoncreds.so' NATIVE/**/*.so
rename 'libanoncreds_uniffi.dylib' 'libuniffi_anoncreds.dylib' NATIVE/**/*.dylib


## TODO missing anoncreds-jvm-1.0-SNAPSHOT.jar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,23 @@ object AnoncredLib {
type SchemaId = String
type CredentialDefinitionId = String

// TODO FIX
// [info] uniffi.anoncreds.AnoncredsException$CreatePresentationException: Create Presentation: Error: Error: Invalid structure
// [info] Caused by: Predicate is not satisfied

def createPresentation(
presentationRequest: PresentationRequest,
credentials: Seq[Credential],
credentialRequests: Seq[CredentialRequests],
selfAttested: Map[String, String],
linkSecret: LinkSecret,
schemas: Map[SchemaId, SchemaDef],
credentialDefinitions: Map[CredentialDefinitionId, CredentialDefinition],
): Presentation = {
): AnoncredPresentation = {
anoncreds
.Prover()
.createPresentation(
presentationRequest,
credentials.map(e => e: uniffi.anoncreds.Credential).asJava, // sequence<Credential> credentials,
credentialRequests.map(i => i: uniffi.anoncreds.CredentialRequests).asJava, // sequence<Credential> credentials,
selfAttested.asJava, // record<string, string>? self_attested,
linkSecret, // LinkSecret link_secret,
schemas.view.mapValues(i => i: uniffi.anoncreds.Schema).toMap.asJava, // record<SchemaId, Schema> schemas,
Expand All @@ -159,8 +163,17 @@ object AnoncredLib {
)
}

// TODO FIX
// uniffi.anoncreds.AnoncredsException$ProcessCredentialException: Verify Presentation: Error:
// Requested restriction validation failed for "{"sex": Some("M")}" attributes [$and operator validation failed.
// [$eq operator validation failed for tag: "attr::sex::value", value: "F" [Proof rejected: "attr::sex::value" values are different: expected: "F", actual: "M"]]]

// TODO FIX
// uniffi.anoncreds.AnoncredsException$ProcessCredentialException: Verify Presentation: Error: Requested restriction validation failed for "{"sex": Some("M")}" attributes [$and operator validation failed. [$eq operator validation failed for tag: "cred_def_id", value: "CRED_DEF_ID" [Proof rejected: "cred_def_id" values are different: expected: "CRED_DEF_ID", actual: "mock:uri3"]]]

// FIXME its always return false ....
def verifyPresentation(
presentation: Presentation,
presentation: AnoncredPresentation,
presentationRequest: PresentationRequest,
schemas: Map[SchemaId, SchemaDef],
credentialDefinitions: Map[CredentialDefinitionId, CredentialDefinition],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import uniffi.anoncreds.{
CredentialOffer as UniffiCredentialOffer,
CredentialRequest as UniffiCredentialRequest,
CredentialRequestMetadata as UniffiCredentialRequestMetadata,
CredentialRequests as UniffiCredentialRequests,
LinkSecret as UniffiLinkSecret,
Schema as UniffiSchema,
Presentation as UniffiPresentation,
PresentationRequest as UniffiPresentationRequest,
Schema as UniffiSchema
}
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder, JsonDecoder, JsonEncoder}

Expand Down Expand Up @@ -257,6 +258,46 @@ object Credential {
}
}

// ****************************************************************************
case class CredentialRequests(
credential: Credential,
requestedAttribute: Seq[String],
requestedPredicate: Seq[String],
)

object CredentialRequests {
given Conversion[CredentialRequests, UniffiCredentialRequests] with {
import uniffi.anoncreds.{RequestedAttribute, RequestedPredicate}
def apply(credentialRequests: CredentialRequests): UniffiCredentialRequests = {
val credential = Credential.given_Conversion_Credential_UniffiCredential(credentialRequests.credential)
val requestedAttributes = credentialRequests.requestedAttribute.map(a => RequestedAttribute(a, true))
val requestedPredicates = credentialRequests.requestedPredicate.map(p => RequestedPredicate(p))
UniffiCredentialRequests(credential, requestedAttributes.asJava, requestedPredicates.asJava)
}
}

given Conversion[UniffiCredentialRequests, CredentialRequests] with {
def apply(credentialRequests: UniffiCredentialRequests): CredentialRequests = {
CredentialRequests(
Credential.given_Conversion_UniffiCredential_Credential(credentialRequests.getCredential()),
credentialRequests
.getRequestedAttribute()
.asScala
.toSeq
.filter(e => e.getRevealed())
.map(e => e.getReferent()),
credentialRequests
.getRequestedPredicate()
.asScala
.toSeq
.map(e => e.getReferent())
)
}
}
}

//UniffiCredentialRequests

// ****************************************************************************

case class PresentationRequest(data: String)
Expand All @@ -274,15 +315,15 @@ object PresentationRequest {

// ****************************************************************************

case class Presentation(data: String)
object Presentation {
given Conversion[Presentation, UniffiPresentation] with {
def apply(presentation: Presentation): UniffiPresentation =
case class AnoncredPresentation(data: String)
object AnoncredPresentation {
given Conversion[AnoncredPresentation, UniffiPresentation] with {
def apply(presentation: AnoncredPresentation): UniffiPresentation =
UniffiPresentation(presentation.data)
}

given Conversion[UniffiPresentation, Presentation] with {
def apply(presentation: UniffiPresentation): Presentation =
Presentation(presentation.getJson())
given Conversion[UniffiPresentation, AnoncredPresentation] with {
def apply(presentation: UniffiPresentation): AnoncredPresentation =
AnoncredPresentation(presentation.getJson())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class PoCNewLib extends AnyFlatSpec {
// ##############
println("*** holder " + ("*" * 100))

val linkSecret = LinkSecretWithId("ID_of_some_secret_1")
val ls1 = LinkSecret("65965334953670062552662719679603258895632947953618378932199361160021795698890")
val linkSecret = LinkSecretWithId("ID_of_some_secret_1", ls1)

val credentialRequest = AnoncredLib.createCredentialRequest(linkSecret, credentialDefinition.cd, credentialOffer)
println("*" * 100)
Expand Down Expand Up @@ -88,7 +89,10 @@ class PoCNewLib extends AnyFlatSpec {
"name":"proof_req_1",
"version":"0.1",
"requested_attributes": {
"sex":{"name":"sex"}
"sex":{"name":"sex", "restrictions":{"attr::sex::value":"M","cred_def_id":"$CRED_DEF_ID"}}
},
"requested_predicates":{
"age":{"name":"age", "p_type":">=", "p_value":18}
}
}""".stripMargin

Expand All @@ -97,8 +101,10 @@ class PoCNewLib extends AnyFlatSpec {

val presentation = AnoncredLib.createPresentation(
presentationRequest, // : PresentationRequest,
Seq(credential), // credentials: Seq[Credential],
Map("sex" -> "M"), // selfAttested: Map[String, String],
Seq(
CredentialRequests(credential, Seq("sex"), Seq("age"))
), // credentials: Seq[Credential],
Map(), // selfAttested: Map[String, String],
linkSecret.secret, // linkSecret: LinkSecret,
Map(credentialOffer.schemaId -> schema), // schemas: Map[SchemaId, SchemaDef],
Map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ final case class ValidIssuedCredentialRecord(
subjectId: Option[String]
)

final case class ValidFullIssuedCredentialRecord(
id: DidCommID,
issuedCredential: Option[IssueCredential],
credentialFormat: CredentialFormat,
schemaId: Option[String],
credentialDefinitionId: Option[UUID],
subjectId: Option[String]
)

object IssueCredentialRecord {

enum Role:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ object PresentationError {
final case class UnsupportedCredentialFormat(vcFormat: String) extends PresentationError
final case class InvalidAnoncredPresentationRequest(error: String) extends PresentationError
final case class MissingAnoncredPresentationRequest(error: String) extends PresentationError

final case class AnoncredPresentationCreationError(cause: Throwable) extends PresentationError
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ trait CredentialRepository {

def getValidIssuedCredentials(recordId: Seq[DidCommID]): RIO[WalletAccessContext, Seq[ValidIssuedCredentialRecord]]

def getValidAnoncredIssuedCredentials(
recordIds: Seq[DidCommID]
): RIO[WalletAccessContext, Seq[ValidFullIssuedCredentialRecord]]

def updateAfterFail(
recordId: DidCommID,
failReason: Option[String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,34 @@ class CredentialRepositoryInMemory(
.toSeq
}

override def getValidAnoncredIssuedCredentials(
recordId: Seq[DidCommID]
): RIO[WalletAccessContext, Seq[ValidFullIssuedCredentialRecord]] = {
for {
storeRef <- walletStoreRef
store <- storeRef.get
} yield store.values
.filter(rec =>
recordId.contains(
rec.id
) && rec.issueCredentialData.isDefined
&& rec.schemaId.isDefined
&& rec.credentialDefinitionId.isDefined
&& rec.credentialFormat == CredentialFormat.AnonCreds
)
.map(rec =>
ValidFullIssuedCredentialRecord(
rec.id,
rec.issueCredentialData,
rec.credentialFormat,
rec.schemaId,
rec.credentialDefinitionId,
rec.subjectId
)
)
.toSeq
}

override def deleteIssueCredentialRecord(recordId: DidCommID): RIO[WalletAccessContext, Int] = {
for {
storeRef <- walletStoreRef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.iohk.atala.pollux.core.service

import io.iohk.atala.mercury.model.DidId
import io.iohk.atala.mercury.protocol.presentproof.{Presentation, ProofType, ProposePresentation, RequestPresentation}
import io.iohk.atala.pollux.anoncreds.AnoncredPresentation
import io.iohk.atala.pollux.core.model.error.PresentationError
import io.iohk.atala.pollux.core.model.presentation.Options
import io.iohk.atala.pollux.core.model.{DidCommID, PresentationRecord}
Expand Down Expand Up @@ -142,12 +143,18 @@ object MockPresentationService extends Mock[PresentationService] {
ignoreWithZeroRetries: Boolean
): IO[PresentationError, Seq[PresentationRecord]] = ???

override def createPresentationPayloadFromRecord(
override def createJwtPresentationPayloadFromRecord(
record: DidCommID,
issuer: Issuer,
issuanceDate: Instant
): IO[PresentationError, PresentationPayload] = ???

override def createAnoncredPresentationPayloadFromRecord(
record: DidCommID,
issuer: Issuer,
issuanceDate: Instant
): IO[PresentationError, AnoncredPresentation] = ???

override def getPresentationRecordsByStates(
ignoreWithZeroRetries: Boolean,
limit: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.iohk.atala.pollux.core.service

import io.iohk.atala.mercury.model.*
import io.iohk.atala.mercury.protocol.presentproof.*
import io.iohk.atala.pollux.anoncreds.AnoncredPresentation
import io.iohk.atala.pollux.core.model.*
import io.iohk.atala.pollux.core.model.error.PresentationError
import io.iohk.atala.pollux.core.model.presentation.*
Expand Down Expand Up @@ -39,12 +40,18 @@ trait PresentationService {
ignoreWithZeroRetries: Boolean
): ZIO[WalletAccessContext, PresentationError, Seq[PresentationRecord]]

def createPresentationPayloadFromRecord(
def createJwtPresentationPayloadFromRecord(
record: DidCommID,
issuer: Issuer,
issuanceDate: Instant
): ZIO[WalletAccessContext, PresentationError, PresentationPayload]

def createAnoncredPresentationPayloadFromRecord(
record: DidCommID,
issuer: Issuer,
issuanceDate: Instant
): ZIO[WalletAccessContext, PresentationError, AnoncredPresentation]

def getPresentationRecordsByStates(
ignoreWithZeroRetries: Boolean,
limit: Int,
Expand Down
Loading

0 comments on commit 1bf9287

Please sign in to comment.