Skip to content

Commit

Permalink
Merge branch 'main' into update/main/sbt
Browse files Browse the repository at this point in the history
  • Loading branch information
yshyn-iohk authored May 29, 2024
2 parents fab81ab + 9d7948f commit ae1061f
Show file tree
Hide file tree
Showing 47 changed files with 2,672 additions and 139 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Setup Java and Scala
uses: olafurpg/setup-scala@v14
with:
java-version: openjdk@1.11
java-version: openjdk@1.17

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/performance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Setup Java and Scala
uses: olafurpg/setup-scala@v14
with:
java-version: openjdk@1.11
java-version: openjdk@1.17

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
Expand Down
20 changes: 15 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ lazy val D = new {
val mockito: ModuleID = "org.scalatestplus" %% "mockito-4-11" % V.mockito % Test
val monocle: ModuleID = "dev.optics" %% "monocle-core" % V.monocle % Test
val monocleMacro: ModuleID = "dev.optics" %% "monocle-macro" % V.monocle % Test
val scalaTest = "org.scalatest" %% "scalatest" % "3.2.16" % Test

val apollo = "io.iohk.atala.prism.apollo" % "apollo-jvm" % V.apollo

Expand Down Expand Up @@ -315,12 +316,10 @@ lazy val D_Pollux_VC_JWT = new {
val zioTestSbt = "dev.zio" %% "zio-test-sbt" % V.zio % Test
val zioTestMagnolia = "dev.zio" %% "zio-test-magnolia" % V.zio % Test

val scalaTest = "org.scalatest" %% "scalatest" % "3.2.16" % Test

// Dependency Modules
val zioDependencies: Seq[ModuleID] = Seq(zio, zioPrelude, zioTest, zioTestSbt, zioTestMagnolia)
val baseDependencies: Seq[ModuleID] =
zioDependencies :+ D.jwtCirce :+ circeJsonSchema :+ networkntJsonSchemaValidator :+ D.nimbusJwt :+ scalaTest
zioDependencies :+ D.jwtCirce :+ circeJsonSchema :+ networkntJsonSchemaValidator :+ D.nimbusJwt :+ D.scalaTest

// Project Dependencies
lazy val polluxVcJwtDependencies: Seq[ModuleID] = baseDependencies
Expand Down Expand Up @@ -419,6 +418,7 @@ publish / skip := true

val commonSetttings = Seq(
testFrameworks ++= Seq(new TestFramework("zio.test.sbt.ZTestFramework")),
libraryDependencies ++= Seq(D.zioTest, D.zioTestSbt, D.zioTestMagnolia),
// Needed for Kotlin coroutines that support new memory management mode
resolvers += "JetBrains Space Maven Repository" at "https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven",
resolvers += "jitpack" at "https://jitpack.io",
Expand Down Expand Up @@ -729,7 +729,7 @@ lazy val polluxCore = project
.dependsOn(shared)
.dependsOn(agentWalletAPI)
.dependsOn(polluxVcJWT)
.dependsOn(vc, resolver, agentDidcommx, eventNotification, polluxAnoncreds)
.dependsOn(vc, resolver, agentDidcommx, eventNotification, polluxAnoncreds, polluxSDJWT)

lazy val polluxDoobie = project
.in(file("pollux/sql-doobie"))
Expand Down Expand Up @@ -761,9 +761,18 @@ lazy val polluxAnoncreds = project

lazy val polluxAnoncredsTest = project
.in(file("pollux/anoncredsTest"))
.settings(libraryDependencies ++= Seq("org.scalatest" %% "scalatest" % "3.2.15" % Test))
.settings(libraryDependencies += D.scalaTest)
.dependsOn(polluxAnoncreds % "compile->test")

lazy val polluxSDJWT = project
.in(file("pollux/sd-jwt"))
.settings(commonSetttings)
.settings(
name := "pollux-sd-jwt",
libraryDependencies += "io.iohk.atala" % "sd-jwt-kmp-jvm" % "0.1.2"
)
.dependsOn(sharedCrypto)

// #####################
// ##### connect #####
// #####################
Expand Down Expand Up @@ -904,6 +913,7 @@ lazy val aggregatedProjects: Seq[ProjectReference] = Seq(
polluxDoobie,
polluxAnoncreds,
polluxAnoncredsTest,
polluxSDJWT,
connectCore,
connectDoobie,
agentWalletAPI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,25 @@ import org.hyperledger.identus.agent.walletapi.model.{ManagedDIDState, Publicati
import org.hyperledger.identus.agent.walletapi.service.ManagedDIDService
import org.hyperledger.identus.castor.core.model.did.{LongFormPrismDID, PrismDID, VerificationRelationship}
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.pollux.vc.jwt.{
DIDResolutionFailed,
DIDResolutionSucceeded,
DidResolver as JwtDidResolver
}
import org.hyperledger.identus.pollux.vc.jwt.*
import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.mercury.{AgentPeerService, DidAgent}
import org.hyperledger.identus.pollux.vc.jwt.{ES256KSigner, Issuer as JwtIssuer}
import org.hyperledger.identus.pollux.vc.jwt.{ES256KSigner, EdSigner, Issuer as JwtIssuer}
import org.hyperledger.identus.shared.models.WalletAccessContext
import zio.{ZIO, ZLayer}
import org.hyperledger.identus.agent.walletapi.storage.DIDNonSecretStorage
import org.hyperledger.identus.agent.walletapi.model.error.DIDSecretStorageError.WalletNotFoundError
import org.hyperledger.identus.shared.crypto.{Ed25519KeyPair, Ed25519PublicKey}
import org.hyperledger.identus.pollux.core.model.error.PresentationError
import org.hyperledger.identus.pollux.sdjwt.SDJWT.*

import java.util.Base64
import org.hyperledger.identus.shared.crypto.KmpEd25519KeyOps
trait BackgroundJobsHelper {

def getLongForm(
Expand Down Expand Up @@ -86,4 +97,84 @@ trait BackgroundJobsHelper {
} yield walletAccessContext
}

def getEd25519SigningKeyPair(
jwtIssuerDID: PrismDID,
verificationRelationship: VerificationRelationship
): ZIO[DIDService & ManagedDIDService & WalletAccessContext, Throwable, Ed25519KeyPair] = {
for {
managedDIDService <- ZIO.service[ManagedDIDService]
didService <- ZIO.service[DIDService]
issuingKeyId <- didService
.resolveDID(jwtIssuerDID)
.mapError(e => RuntimeException(s"Error occured while resolving Issuing DID during VC creation: ${e.toString}"))
.someOrFail(RuntimeException(s"Issuing DID resolution result is not found"))
.map { case (_, didData) => didData.publicKeys.find(_.purpose == verificationRelationship).map(_.id) }
.someOrFail(
RuntimeException(s"Issuing DID doesn't have a key in ${verificationRelationship.name} to use: $jwtIssuerDID")
)
ed25519keyPair <- managedDIDService
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingKeyId)
.map(_.collect { case keyPair: Ed25519KeyPair => keyPair })
.mapError(e => RuntimeException(s"Error occurred while getting issuer key-pair: ${e.toString}"))
.someOrFail(
RuntimeException(s"Issuer key-pair does not exist in the wallet: ${jwtIssuerDID.toString}#$issuingKeyId")
)
} yield ed25519keyPair
}

/** @param jwtIssuerDID
* This can holder prism did / issuer prism did
* @param verificationRelationship
* Holder it Authentication and Issuer it is AssertionMethod
* @return
* JwtIssuer
* @see
* org.hyperledger.identus.pollux.vc.jwt.Issuer
*/
def getSDJwtIssuer(
jwtIssuerDID: PrismDID,
verificationRelationship: VerificationRelationship
): ZIO[DIDService & ManagedDIDService & WalletAccessContext, Throwable, JwtIssuer] = {
for {
ed25519keyPair <- getEd25519SigningKeyPair(jwtIssuerDID, verificationRelationship)
} yield {
JwtIssuer(
org.hyperledger.identus.pollux.vc.jwt.DID(jwtIssuerDID.toString),
EdSigner(ed25519keyPair),
Ed25519PublicKey.toJavaEd25519PublicKey(ed25519keyPair.publicKey.getEncoded)
)
}
}

def resolveToEd25519PublicKey(did: String): ZIO[JwtDidResolver, PresentationError, Ed25519PublicKey] = {
for {
didResolverService <- ZIO.service[JwtDidResolver]
didResolutionResult <- didResolverService.resolve(did)
publicKeyBase64 <- didResolutionResult match {
case failed: DIDResolutionFailed =>
ZIO.fail(
PresentationError.UnexpectedError(
s"DIDResolutionFailed for $did: ${failed.error.toString}"
)
)
case succeeded: DIDResolutionSucceeded =>
succeeded.didDocument.verificationMethod
.find(vm => succeeded.didDocument.assertionMethod.contains(vm.id))
.flatMap(_.publicKeyJwk.flatMap(_.x))
.toRight(
PresentationError.UnexpectedError(
s"Did Document is missing the required publicKey: $did"
)
)
.fold(ZIO.fail(_), ZIO.succeed(_))
}
ed25519PublicKey <- ZIO
.fromTry {
val decodedKey = Base64.getUrlDecoder.decode(publicKeyBase64)
KmpEd25519KeyOps.publicKeyFromEncoded(decodedKey)
}
.mapError(t => PresentationError.UnexpectedError(t.getMessage))
} yield ed25519PublicKey
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,47 @@ object IssueBackgroundJobs extends BackgroundJobsHelper {
.gauge("issuance_flow_holder_req_pending_to_generated_flow_ms_gauge")
.trackDurationWith(_.toMetricsSeconds)

case IssueCredentialRecord(
id,
_,
_,
_,
_,
_,
_,
CredentialFormat.SDJWT,
Role.Holder,
Some(subjectId),
_,
_,
RequestPending,
Some(offer),
None,
_,
_,
_,
_,
_,
_,
_
) =>
val holderPendingToGeneratedFlow = for {
walletAccessContext <- buildWalletAccessContextLayer(offer.to)
result <- (for {
credentialService <- ZIO.service[CredentialService]
_ <- credentialService
.generateSDJWTCredentialRequest(id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext))
} yield ()).mapError(e => (walletAccessContext, handleCredentialErrors(e)))
} yield result

holderPendingToGeneratedFlow @@ HolderPendingToGeneratedSuccess.trackSuccess
@@ HolderPendingToGeneratedFailed.trackError
@@ HolderPendingToGeneratedAll
@@ Metric
.gauge("issuance_flow_holder_req_pending_to_generated_flow_ms_gauge")
.trackDurationWith(_.toMetricsSeconds)

case IssueCredentialRecord(
id,
_,
Expand Down Expand Up @@ -420,6 +461,52 @@ object IssueBackgroundJobs extends BackgroundJobsHelper {
.gauge("issuance_flow_issuer_cred_pending_to_generated_flow_ms_gauge")
.trackDurationWith(_.toMetricsSeconds)

// Credential is pending, can be generated by Issuer
case IssueCredentialRecord(
id,
_,
_,
_,
_,
_,
_,
CredentialFormat.SDJWT,
Role.Issuer,
_,
_,
_,
CredentialPending,
_,
_,
_,
Some(issue),
_,
Some(issuerDID),
_,
_,
_,
) =>
// Generate the JWT Credential and store it in DB as an attachment to IssueCredentialData
// Set ProtocolState to CredentialGenerated
// TODO Move all logic to service
val issuerPendingToGeneratedFlow = for {
walletAccessContext <- buildWalletAccessContextLayer(issue.from)
result <- (for {
credentialService <- ZIO.service[CredentialService]
config <- ZIO.service[AppConfig]
_ <- credentialService
.generateSDJWTCredential(id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext))
} yield ()).mapError(e => (walletAccessContext, e))
} yield result

issuerPendingToGeneratedFlow @@ IssuerPendingToGeneratedSuccess.trackSuccess
@@ IssuerPendingToGeneratedFailed.trackError
@@ IssuerPendingToGeneratedAll
@@ Metric
.gauge("issuance_flow_issuer_cred_pending_to_generated_flow_ms_gauge")
.trackDurationWith(_.toMetricsSeconds)

case IssueCredentialRecord(
id,
_,
Expand Down
Loading

0 comments on commit ae1061f

Please sign in to comment.