Skip to content

Commit

Permalink
Merge branch 'rajesh.kalaria_ve3569_fix-fq-identifier-issues' into 'm…
Browse files Browse the repository at this point in the history
…ain'

VE-3569: fix fq identifier issues

See merge request evernym/verity/verity!620
  • Loading branch information
Rajesh Kalaria committed Aug 17, 2022
2 parents c87f65c + 2d4d63a commit d519d8a
Show file tree
Hide file tree
Showing 85 changed files with 1,264 additions and 1,186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import com.evernym.verity.did.{DidPair, DidStr}

import scala.concurrent.Future

case class LedgerExecutorException(message: String,
cause: Throwable = None.orNull) extends Exception(message, cause)

trait LedgerTxnExecutor {

//NOTE: this `addNym` is only used by tests, may be we should replace it with vdr api calls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import com.evernym.verity.protocol.engine._
import com.evernym.verity.protocol.engine.context.{ProtocolContextApi, Roster}
import com.evernym.verity.protocol.engine.util.?=>
import com.evernym.verity.util.OptionUtil
import com.evernym.verity.vdr.{CredDefId, DID_PREFIX}
import com.typesafe.scalalogging.Logger
import org.json.{JSONException, JSONObject}

import scala.util.{Failure, Success, Try}

trait ProtocolHelpers[P,R,M,E,S,I] {
type Context = ProtocolContextApi[P, R, M, E, S, String]
Expand Down Expand Up @@ -70,6 +74,37 @@ trait ProtocolHelpers[P,R,M,E,S,I] {
def buildQualifiedIdentifier(identifier: Option[DidStr])(implicit ctx: Context): Option[DidStr] = {
ProtocolHelpers.buildQualifiedIdentifier(identifier, ctx)
}

def downgradeIdentifiersIfRequired(jsonStr: String,
identifier: String,
isMultiLedgerSupportEnabled: Boolean)
(implicit ctx: Context): String = {
val isFQIdentifier = identifier.startsWith(DID_PREFIX)
if (isFQIdentifier && !isMultiLedgerSupportEnabled) {
JsonValueReplacer(jsonStr)
.replaceIfExists(ISSUER_DID, ctx.vdr.toLegacyNonFqId)
.replaceIfExists(SCHEMA_ID, ctx.vdr.toLegacyNonFqSchemaId)
.replaceIfExists(CRED_DEF_ID, ctx.vdr.toLegacyNonFqCredDefId)
.jsonString
} else {
jsonStr
}
}

def extractOptionalField(json: String, fieldName: String): Option[String] = {
Try {
val jsonObject = new JSONObject(json)
jsonObject.getString(fieldName)
}.toOption
}

def extractCredDefId(json: String): CredDefId = {
extractOptionalField(json, CRED_DEF_ID).getOrElse(throw new RuntimeException(s"'$CRED_DEF_ID' not found"))
}

val ISSUER_DID = "issuer_did"
val SCHEMA_ID = "schema_id"
val CRED_DEF_ID = "cred_def_id"
}

object ProtocolHelpers {
Expand All @@ -93,3 +128,14 @@ object ProtocolHelpers {
}
}
}

case class JsonValueReplacer(jsonString: String) {
def replaceIfExists(fieldName: String, replacerWith: String => String): JsonValueReplacer = {
val jsonObject = new JSONObject(jsonString)
Try(jsonObject.getString(fieldName)) match {
case Success(value) => JsonValueReplacer(jsonObject.put(fieldName, replacerWith(value)).toString)
case Failure(_: JSONException) => this
case Failure(e) => throw e
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ import com.evernym.verity.protocol.protocols.outofband.v_1_0.InviteUtil
import com.evernym.verity.protocol.protocols.outofband.v_1_0.Msg.prepareInviteUrl
import com.evernym.verity.urlshortener.{UrlShortened, UrlShorteningFailed}
import com.evernym.verity.util.{MsgIdProvider, OptionUtil}
import com.evernym.verity.vdr.CredDef
import org.json.JSONObject
import com.evernym.verity.vdr.{CredDef, CredDefId}

import scala.util.{Failure, Success, Try}

Expand Down Expand Up @@ -166,13 +165,13 @@ object IssueCredential {
extractString(attachment)
}

def getCredentialDataFromMessage(credentialValues: Map[String, String]): String = {
val jsonObject: JSONObject = new JSONObject()
for ((key, value) <- credentialValues) {
jsonObject.put(key, value)
}
jsonObject.toString()
}
// def getCredentialDataFromMessage(credentialValues: Map[String, String]): String = {
// val jsonObject: JSONObject = new JSONObject()
// for ((key, value) <- credentialValues) {
// jsonObject.put(key, value)
// }
// jsonObject.toString()
// }

def setSenderRole(senderId: String, senderRole: Role, roster: Roster[Role]): Roster[Role] = {
val r = roster.withParticipant(senderId)
Expand Down Expand Up @@ -307,7 +306,8 @@ trait IssueCredentialHelpers
))

if(!m.by_invitation.getOrElse(false)) {
ctx.send(offer)
val adaptedOfferCred = downgradeOfferCredIdentifiersIfRequired(offer, m.cred_def_id, ctx.vdr.isMultiLedgerSupportEnabled)
ctx.send(adaptedOfferCred)
ctx.signal(Sig.Sent(offer))
}
else sendInvite(offer, s)
Expand Down Expand Up @@ -339,7 +339,8 @@ trait IssueCredentialHelpers
s.segmentKey,
m.auto_issue.getOrElse(false)
))
ctx.send(offer)
val adaptedOfferCred = downgradeOfferCredIdentifiersIfRequired(offer, m.cred_def_id, ctx.vdr.isMultiLedgerSupportEnabled)
ctx.send(adaptedOfferCred)
ctx.signal(Sig.Sent(offer))
case Failure(e) =>
ctx.signal(
Expand Down Expand Up @@ -385,7 +386,7 @@ trait IssueCredentialHelpers
val credOfferJson = extractCredOfferJson(credOffer)
ctx.wallet.createCredReq(m.cred_def_id, myPwDid, credDefJson, credOfferJson) {
case Success(credRequest: CredReqCreatedResult) =>
val attachment = buildAttachment(Some("libindy-cred-req-0"), payload=credRequest.credReqJson)
val attachment = buildAttachment(Some(LIBINDY_CRED_REQ_0), payload=credRequest.credReqJson)
val attachmentEventObject = toAttachmentObject(attachment)
val credRequested = CredRequested(Seq(attachmentEventObject), commentReq(m.comment))
//TODO: store cred req metadata to be used later on
Expand Down Expand Up @@ -449,20 +450,23 @@ trait IssueCredentialHelpers
`~please_ack`: Option[PleaseAck]=None): Unit = {
val credOfferJson = extractCredOfferJson(credOffer)
val credReqJson = extractCredReqJson(credRequest)
val credDefId = extractCredDefId(credOfferJson)
val credValuesJson = IssueCredential.buildCredValueJson(credOffer.credential_preview)

ctx.wallet.createCred(credOfferJson, credReqJson, credValuesJson, revRegistryId.orNull, -1) {
case Success(createdCred: CredCreatedResult) =>
val attachment = buildAttachment(Some("libindy-cred-0"), payload=createdCred.cred)
val attachmentEventObject = toAttachmentObject(attachment)
val credIssued = CredIssued(Seq(attachmentEventObject), commentReq(comment))
val attachment = buildAttachment(Some(LIBINDY_CRED_0), payload=createdCred.cred)
val credIssued = CredIssued(Seq(toAttachmentObject(attachment)), commentReq(comment))

ctx.storeSegment(segment = credIssued) {
case Success(s) =>
ctx.apply(IssueCredSent(s.segmentKey))
val issueCred = IssueCred(Vector(attachment), Option(credIssued.comment), `~please_ack` = `~please_ack`)
ctx.send(issueCred)
ctx.signal(Sig.Sent(issueCred))
case Failure(e) =>
val adaptedCred = downgradeIdentifiersIfRequired(createdCred.cred, credDefId, ctx.vdr.isMultiLedgerSupportEnabled)
val adaptedAttachment = buildAttachment(Some(LIBINDY_CRED_0), payload=adaptedCred)
val adaptedIssueCred = IssueCred(Vector(adaptedAttachment), Option(credIssued.comment), `~please_ack` = `~please_ack`)
ctx.send(adaptedIssueCred)
ctx.signal(Sig.Sent(adaptedIssueCred))
case Failure(_) =>
ctx.signal(
Sig.buildProblemReport(
s"cred issuance failed",
Expand Down Expand Up @@ -610,7 +614,7 @@ trait IssueCredentialHelpers
case Success(coc: CredOfferCreatedResult) =>
val credPreview = buildCredPreview(m.credential_values)
val credPreviewEventObject = credPreview.toOption.map(_.toCredPreviewObject)
val attachment = buildAttachment(Some("libindy-cred-offer-0"), payload = coc.offer)
val attachment = buildAttachment(Some(LIBINDY_CRED_OFFER_0), payload = coc.offer)
val attachmentEventObject = toAttachmentObject(attachment)

val credOffered = CredOffered(
Expand Down Expand Up @@ -713,4 +717,20 @@ trait IssueCredentialHelpers
def commentReq(comment: Option[String]): String = {
comment.getOrElse("")
}

private def downgradeOfferCredIdentifiersIfRequired(o: OfferCred,
credDefId: CredDefId,
isMultiLedgerSupportEnabled: Boolean): OfferCred = {
val adaptedAttachments = o.`offers~attach`.map { attach =>
val jsonString = extractString(attach)
val adaptedJson = downgradeIdentifiersIfRequired(jsonString, credDefId, isMultiLedgerSupportEnabled)
buildAttachment(Some(LIBINDY_CRED_OFFER_0), adaptedJson)
}

OfferCred(o.credential_preview, adaptedAttachments, o.comment, o.price)
}

private val LIBINDY_CRED_OFFER_0 = "libindy-cred-offer-0"
private val LIBINDY_CRED_REQ_0 = "libindy-cred-req-0"
private val LIBINDY_CRED_0 = "libindy-cred-0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class PresentProof(implicit val ctx: PresentProofContext)

def handleMsgPresentation(msg: Msg.Presentation)(requestUsed: RequestUsed): Unit = {
recordSenderId()
val proofRequest = DefaultMsgCodec.fromJson[ProofRequest](requestUsed.requestRaw)
val proofRequest = adaptedProofReq(DefaultMsgCodec.fromJson[ProofRequest](requestUsed.requestRaw))
val proofRequestJson = DefaultMsgCodec.toJson(_checkRevocationInterval(proofRequest))

extractPresentation(msg) match {
Expand Down Expand Up @@ -319,16 +319,52 @@ class PresentProof(implicit val ctx: PresentProofContext)
case Success(s) =>
ctx.apply(RequestUsedRef(s.segmentKey))

val presentationRequest = Msg.RequestPresentation("", Vector(buildAttachment(Some(AttIds.request0), str)))
if(!ctr.by_invitation.getOrElse(false)) { ctx.send(presentationRequest) }
else { sendInvite(presentationRequest, stateData) }
if(!ctr.by_invitation.getOrElse(false)) {
val proofReq = adaptedProofReq(proofRequest.get)
val adaptedProofReqJson = DefaultMsgCodec.toJson(proofReq)
val presentationRequest = Msg.RequestPresentation("", Vector(buildAttachment(Some(AttIds.request0), adaptedProofReqJson)))
ctx.send(presentationRequest)
} else {
val presentationRequest = Msg.RequestPresentation("", Vector(buildAttachment(Some(AttIds.request0), str)))
sendInvite(presentationRequest, stateData)
}
case Failure(e) => reportSegStoreFailed("error during processing request")
}
case Failure(e) =>
signal(Sig.buildProblemReport(s"Invalid Request -- ${e.getMessage}", invalidRequestedPresentation))
}
}

private def adaptedProofReq(pr: ProofRequest): ProofRequest = {
val reqAttributes: Map[String, ProofAttribute] =
pr.requested_attributes.map { item =>
val adaptedRestrictions = item._2.restrictions.map(adaptedRestrictionsIdentifiers)
item._1 -> item._2.copy(restrictions = adaptedRestrictions)
}

val reqPredicates: Map[String, ProofPredicate] =
pr.requested_predicates.map { item =>
val adaptedRestrictions = item._2.restrictions.map(adaptedRestrictionsIdentifiers)
item._1 -> item._2.copy(restrictions = adaptedRestrictions)
}

pr.copy(requested_attributes = reqAttributes, requested_predicates = reqPredicates)
}

private def adaptedRestrictionsIdentifiers(restrictions: List[RestrictionsV1]): List[RestrictionsV1] = {
restrictions
.map { restriction =>
val identifierOption = List(restriction.cred_def_id, restriction.schema_id, restriction.issuer_did).head
identifierOption match {
case Some(identifier) =>
val restrictionJson = DefaultMsgCodec.toJson(restriction)
val adaptedRestrictionJson = downgradeIdentifiersIfRequired(restrictionJson, identifier, ctx.vdr.isMultiLedgerSupportEnabled)
DefaultMsgCodec.fromJson[RestrictionsV1](adaptedRestrictionJson)
case None => restriction
}
}
}

def sendInvite(presentationRequest: Msg.RequestPresentation, stateData: StateData): Unit = {
buildOobInvite(definition.protoRef, presentationRequest, stateData) {
case Success(invite) =>
Expand Down Expand Up @@ -592,11 +628,11 @@ object PresentProof {
.forall(identity)
}

def credentialsToUse(credentialsNeeded: Try[AvailableCredentials],
def credentialsToUse(availableCredentials: Try[AvailableCredentials],
selfAttestedAttributes: Map[String, String]=Map.empty): (Try[String], Set[(String, String)]) = {
val ids: mutable.Buffer[(String,String)] = mutable.Buffer()

val credentialsUsedJson = credentialsNeeded
val credentialsUsedJson = availableCredentials
.map{ creds =>
val requestedAttributes: Map[String, AttributeUsed] = creds.attrs
.foldLeft(Map[String, AttributeUsed]()) { (col, entity) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._


class ActorWalletService(system: ActorSystem, appConfigParam: AppConfig, poolConnManager: LedgerPoolConnManager, executionContext: ExecutionContext)
class ActorWalletService(system: ActorSystem,
appConfigParam: AppConfig,
poolConnManager: LedgerPoolConnManager,
executionContext: ExecutionContext)
extends WalletService with ShardUtil {

override def appConfig: AppConfig = appConfigParam
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ trait LedgerTxnExecutorBase extends LedgerTxnExecutor with HasExecutionContextPr
}

object LedgerTxnUtil {
def appendTAAToRequest(ledgerRequest: LedgerRequest, taa: Option[TransactionAuthorAgreement])
def appendTAAToRequest(ledgerRequest: LedgerRequest,
taa: Option[TransactionAuthorAgreement])
(implicit ec: ExecutionContext): Future[LedgerRequest] = {
// IMPORTANT - Either use (text and version) OR (digest). Sending text or version with digest will result
// in an IndyException - Error: Invalid structure Caused by: Invalid combination of params:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class MockAgentActorContext(val system: ActorSystem,
lazy val vdrTools: VdrTools = vdrBuilderFactory().build()
override lazy val vdrAdapter: VDRAdapter = createVDRAdapter(vdrTools)
override lazy val legacyLedgerSvc: LegacyLedgerSvc = new MockLegacyLedgerSvc(appConfig, vdrAdapter)
override lazy val poolConnManager: LedgerPoolConnManager = new InMemLedgerPoolConnManager(ecp.futureExecutionContext, appConfig, vdrAdapter)(system.dispatcher)
override lazy val poolConnManager: LedgerPoolConnManager = new InMemLedgerPoolConnManager(ecp.futureExecutionContext, appConfig, vdrAdapter)
override lazy val agentMsgRouter: AgentMsgRouter = mockAgentMsgRouter.getOrElse(
new MockAgentMsgRouter(executionContext)(appConfig, system)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,12 @@ import com.evernym.verity.agentmsg.msgfamily.configs.UpdateConfigReqMsg
import com.evernym.verity.integration.base.sdk_provider.SdkProvider
import com.evernym.verity.protocol.protocols.issuersetup.v_0_6.IssuerSetup.alreadyCreatingProblem
import com.evernym.verity.protocol.protocols.issuersetup.v_0_6.{Create, IssuerSetupDefinition, ProblemReport, PublicIdentifierCreated}
import com.evernym.verity.util.TestExecutionContextProvider
import com.evernym.verity.util2.ExecutionContextProvider

import scala.concurrent.ExecutionContext

class ActorStateModifierSpec
extends VerityProviderBaseSpec
with SdkProvider {

lazy val ecp = TestExecutionContextProvider.ecp
lazy val executionContext: ExecutionContext = ecp.futureExecutionContext

lazy val issuerVerityEnv = VerityEnvBuilder.default().build(VAS)
lazy val issuerVerityEnv = VerityEnvBuilder().build(VAS)
lazy val issuerSDK = setupIssuerSdk(issuerVerityEnv, executionContext)

override def beforeAll(): Unit = {
Expand Down Expand Up @@ -63,9 +56,4 @@ class ActorStateModifierSpec
}
}
}


override def futureExecutionContext: ExecutionContext = executionContext

override def executionContextProvider: ExecutionContextProvider = ecp
}
Loading

0 comments on commit d519d8a

Please sign in to comment.