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

Assessment of VC Schema Alignment with EAS x Ceramic Collaboration #1935

Open
7 tasks done
erichfi opened this issue Nov 21, 2023 · 9 comments · May be fixed by #1964
Open
7 tasks done

Assessment of VC Schema Alignment with EAS x Ceramic Collaboration #1935

erichfi opened this issue Nov 21, 2023 · 9 comments · May be fixed by #1964
Assignees

Comments

@erichfi
Copy link
Collaborator

erichfi commented Nov 21, 2023

Objective:

To conduct a swift, one-day investigation into our current VC schema against the EAS x Ceramic collaboration, ensuring our approach is aligned with the latest standards and practices before our migration to ComposeDB.

Background:

With the strategic move to Ceramic ComposeDB on the horizon, it's essential to verify that our VC schema is in line with the latest industry developments, specifically the collaboration between EAS and Ceramic.

Key Questions:

  • Are there elements in the EAS x Ceramic schema that offer significant benefits over our chosen schema?
  • How does our current VC schema compare in terms of interoperability and future-readiness with the EAS x Ceramic standards?
  • What are the implications of adopting the EAS x Ceramic schema for our migration strategy and operational continuity?

Tasks:

  • Review the EAS Ceramic Storage Documentation: EAS x Ceramic Documentation.
  • Examine our current VC schema as specified in our GitHub issue: Our VC Schema Issue.
  • Identify and document key differences, advantages, and potential drawbacks between the two schemas.
  • Outline the technical feasibility and strategic value of aligning with the EAS x Ceramic collaboration.
  • Summarize findings and prepare a recommendation on the schema direction.
  • Expected Outcome:
  • A concise report detailing the findings of the VC schema comparison, including an evaluation of the potential for schema alignment and recommendations for the migration to ComposeDB.

Time Frame:
The investigation will be timeboxed to one day, with findings to be presented at the end of the day.

Deliverables:

  • Comparative analysis of the VC schemas within the stipulated timeframe.
  • Documentation of any identified risks and opportunities with the EAS x Ceramic schema.
  • A set of recommendations for our VC schema approach, considering the insights gained.
@erichfi erichfi changed the title Dig https://docs.attest.sh/docs/tutorials/ceramic-storage Investigate EAS Collaboration with Ceramic for VC Schema Compatibility Nov 22, 2023
@erichfi erichfi changed the title Investigate EAS Collaboration with Ceramic for VC Schema Compatibility Evaluating VC Schema Alignment with EAS x Ceramic Collaboration Before Migrating to ComposeDB Nov 22, 2023
@erichfi erichfi changed the title Evaluating VC Schema Alignment with EAS x Ceramic Collaboration Before Migrating to ComposeDB Assessment of VC Schema Alignment with EAS x Ceramic Collaboration Nov 22, 2023
@mzkrasner
Copy link
Contributor

mzkrasner commented Nov 29, 2023

Just catching myself up to speed here on the passport side, so apologies in advance if I misunderstand the current architecture in any way. I created the EAS x Ceramic guide, so hopefully I'll be able to share some helpful insight there.

As you've seen, the example I used in the EAS x Ceramic off-chain attestation guide used a simple MetIRL Schema that only took in a boolean value, while the issuer and recipient are defined when the issuing event occurs.

Also, if my understanding of this example implementation is correct, there would presumably be one static issuer of each off-chain passport attestation (unlike the EAS x Ceramic example).

Putting the current deployed Passport Stamps V1 definitions aside for a moment and looking only at the values within a passport vc vs my understanding of how one would issue an off-chain passport attestation with the same fields, I'd imagine the schema types needed would just be:

  • provider: string (for example, 'Twitter')
  • hash: Bytes32 (just like the example above)
  • issuanceDate: Uint64
  • ExpirationDate: Unt64

Using ComposeDB, we could define a general attestation interface that each individual provider could implement, thus opening up multiple entrypoints. For example:

interface Attestation 
@createModel(description: "An attestation interface")
{
  publisher: DID! @documentAccount 
  uid: String! @string(minLength: 66, maxLength: 66)
  schema: String! @string(minLength: 66, maxLength: 66)
  attester: String! @string(minLength: 42, maxLength: 42)
  verifyingContract: String! @string(minLength: 42, maxLength: 42)
  easVersion: String! @string(maxLength: 5)
  version: Int!
  chainId: Int! 
  r: String! @string(minLength: 66, maxLength: 66)
  s: String! @string(minLength: 66, maxLength: 66)
  v: Int! 
  types: [Types] @list(maxLength: 100)
  recipient: String @string(minLength: 42, maxLength: 42)
  expirationTime: DateTime
  revocationTime: DateTime
  refUID: String @string(minLength: 66, maxLength: 66)
  time: Int! 
  data: String! @string(maxLength: 1000000)
}

type Types {
  name: String! @string(maxLength: 20)
  type: String! @string(maxLength: 20)
}

type TwitterVerification implements Attestation 
  @createModel(accountRelation: LIST, description: "An account attestation")
  @createIndex(fields: [{ path: ["attester"] }])
  @createIndex(fields: [{ path: ["recipient"] }])
  @createIndex(fields: [{ path: ["time"] }])
{
  publisher: DID! @documentAccount 
  uid: String! @string(minLength: 66, maxLength: 66)
  schema: String! @string(minLength: 66, maxLength: 66)
  attester: String! @string(minLength: 42, maxLength: 42)
  verifyingContract: String! @string(minLength: 42, maxLength: 42)
  easVersion: String! @string(maxLength: 5)
  version: Int!
  chainId: Int! 
  r: String! @string(minLength: 66, maxLength: 66)
  s: String! @string(minLength: 66, maxLength: 66)
  v: Int! 
  types: [Types] @list(maxLength: 100)
  recipient: String @string(minLength: 42, maxLength: 42)
  expirationTime: DateTime
  revocationTime: DateTime
  refUID: String @string(minLength: 66, maxLength: 66)
  time: Int! 
  data: String! @string(maxLength: 1000000)
}

When generating the offchain instances, the data values themselves (the key-values for things like provider, etc) get encoded and signed (EIP712), so the ComposeDB storage definitions are intended to save both the encoded data, as well as the signatures needed to later validate to prove they have not been tampered with, if necessary.

In the current Ceramic x EAS repo, you'll notice that the individual user is creating and signing each attestation, while an API is called thereafter to write the attestation to ComposeDB using a static key:did. For each Gitcoin issuance, one difference here is that both the offchain issuance and the writing to ComposeDB would be done server-side by a static key, which would honestly simplify things further.

I'm happy to make a branch within our EAS + Ceramic repo to show POC for this if you'd like. IMO, it would a fairly light lift to retrofit the existing code to create offchain passport attestations, and most of the decision-making would be around how to translate those payloads into composeDB schemas that support the type of querying you'll need.

@lucianHymer lucianHymer self-assigned this Nov 30, 2023
@lucianHymer
Copy link
Collaborator

@mzkrasner Awesome, thank you so much for all this info and for digging into this!

So it seems like the main change here is that the attestations do not contain the signature, instead the attestation itself is signed and written to Ceramic by the issuer (us). And so this means that the credential will be part of our Ceramic stream, not the users' streams.

This is pretty different from how we issue our credentials now. Currently, the credential itself includes our signature for the credentialSubject, so we can pass the credential around and have anybody store it wherever they want and we can still see that it's a valid credential that we issued. In the current architecture, the user writes this to their Ceramic stream and to our database (validated with the same did-session as their ceramic stream).

@mzkrasner have you guys considered some sort of AttestationVC or AttestationByOther (I'm having trouble thinking of a good name right now haha) that would include a signature for some subset of the data? Maybe even include verification of that signature when verifying the offchain attestation?

@lucianHymer
Copy link
Collaborator

lucianHymer commented Nov 30, 2023

More broadly speaking, it seems like we've ended up with two distinct ways of representing passports:

  1. Attestations
  2. VCs

The Attestation could be an attestation about the state of one or more credentials in a passport, or an attestation about the score of a passport at a particular time

VCs are basically a credential attestation wrapped in some additional data that can be used to verify it. We don't currently issue VCs for scores.

It's easy to go from a VC to an attestation, and also possible to go from an attestation to a pseudo-VC if we either 1. hang on to the signature and tie it with the attestation or 2. we're the issuer and we can re-sign it.

We can store both attestations and VCs in any storage mechanism (onchain with EAS, offchain in ceramic or our DB, etc.).

With our EAS implementation, we're signing an attestation and then passing this attestation and signature back to the user (this is sort of a pseudo-VC at this point. Now that we've got the EIP-712 credentials, we could just pass those real VCs back to the user instead.). The user writes this onchain, paying for the transaction themself. Our contract verifies the attestation signature and then writes the attestation to EAS.

One worry about switching to attestations that we issue directly to ComposeDB from our backend is that we'll be on the hook if Ceramic starts charging a fee. And then we'd have to scramble to re-architect everything, or pay the fees ourselves.

@lucianHymer
Copy link
Collaborator

lucianHymer commented Nov 30, 2023

It would be a simpler system overall if we were just writing directly to our DB and our Ceramic stream from our backend. But I like how it's a bit more self-sovereign at this point. Technically anybody could use our backend to get VCs and then store them wherever they want.

I might just be into the narrative, and it may not make a difference in the end. But we sure do like our narratives in crypto haha.

@nutrina
Copy link
Collaborator

nutrina commented Dec 4, 2023

Hey @mzkrasner thanks for providing this detailed example.
@lucianHymer I have a bit of a different perspective on this.

From my point of view, both VCs and Off-chain Attestations are self-contained records.
Both contain:

  • some metadata
  • payload
  • signature / proof attesting the validity of the data

The VCs are issued and signed by our backend, and we can do the same with EAS attestation (I have not tested yet, I have only tested off-chain attestation issues in the browser, but I see no impediment in doing this).
And in both case we can store the data (JSON object) wherever we choose, for example in a DB, on ceramic, in the users local storage, or convert to a QR code).
Even more, once we switch our VC format to use EIP-712 signatures, the 2 approaches will become even more similar.

So, the 2 formats from my perspective are interchangeable (at least for the current use-case that we have).

The current schema that we have for writing passports on-chain however, I think is not well suited for off-chain usage, because we have binary-encoded all the users VCs into a single structure to save gas. So using this schema for off-chain data is hard and I would not go this route.

However if we are thinking of creating a attestation schema for a single VC on EAS, then this could really be a replacement for our current VCs. We would then essentially have an attestations and a VC with the exact payload, and each having a signature attesting to that payload, but in a different data structure.

There are also other aspects to consider of course (for example revocations- but both formats support this ...).

@nutrina nutrina linked a pull request Dec 4, 2023 that will close this issue
@nutrina
Copy link
Collaborator

nutrina commented Dec 4, 2023

@lucianHymer I have created an overview for showing the current data flow: https://app.diagrams.net/#Hgitcoinco%2Fpassport%2F1935_data_flow%2Fdocs%2FOverview.md

It's stored in the branch linked to this ticket ....

@lucianHymer
Copy link
Collaborator

@nutrina Okay interesting, I misinterpreted this ticket I think.

So I think the VC is self-contained, but the attestation either 1. needs to be written to Ceramic by the attester or 2. we have to make sure to hold on to the signature and pass it around with the attestation (not as part of the attestation itself, the schema doesn't support that), and ensure that some process is verifying this signature (like we're doing now with our onchain attestations).

It's sort of just semantic, we can make either work. But if we were to write offchain Attestations of the above format to Ceramic, we would have to do it directly from our backend which is a deviation from how we're handling things currently. But perhaps that's fine, we mostly did it this way to avoid paying users' gas.

@mzkrasner
Copy link
Contributor

Apologies for my delay - just catching up on this thread now.

@lucianHymer - appreciate you explaining the current setup (being that the credentials themselves are signed by Gitcoin, but the stream is controlled by the user).

Both VCs and off-chain attestations are tamper-evident, so you could still create the same setup for allowing users to store their own attestations that are signed by passport, and can be passed around and validated where and when validation is needed. EAS's off-chain attestation verification methods function similarly to a VC lib like Veramo, so as @nutrina mentioned, regardless of who owns the Ceramic stream (user vs some static server), the validation calls can tell whether it's been tampered with or not

@nutrina
Copy link
Collaborator

nutrina commented Dec 12, 2023

I have compared the following scenarios:

Scenario A - Gitcoin Passport implements writing VCs to compose DB. This would follow the VC specification (this is already on our roadmap).

Scenario B - EAS off-chain attestation: a user writes his stamps as EAS off-chain attestations to ComposeDB (this is currently a hypothetical scenario, we only use EAS for creating on-chain attestations atm.)

In both cases we end up having a JSON document that is signed by the same party (the Gitcoin Issuer) that is stored on ComposeDB.
The difference will be in the structure of the JSON document:

  • the VC one will follow the VC document schema specification and can potentially support multiple proofs type (signature types). We are planning however to move to EIP-712 for compatibility with solidity.
  • the EAS off-chain format is proprietary. The attestation will however contain the same payload and it also uses an EIP-712 signature. But the payload is encoded (binary) which is a disadvantage when looking at the JSON document, and cannot read the payload without a decoder.

For our use-case, we could also switch from one format to the other (from VC to EAS off-chain attestation).
But this would come at the cost of adding support for the EAS format (handling the attestation document, reading & decoding the payload, check the validity ...).

If on the other hand EAS would allow writing off-chain attestations in a VC format (instead of the proprietary one) and preferably not ABI-encode the payload into a byte-string then loading these attestation would be easier, we could essentially introduce support for loading EAS off-chain attestation from Ceramic for example, and stick to the same tooling.

To the key questions in this tickets description:

Are there elements in the EAS x Ceramic schema that offer significant benefits over our chosen schema?

Answer: No. We can also use EAS off-chain attestations to store our stamps, but sticking to VC seems currently the better choice, also because of the wider support (multiple libraries across several languages), and the payload is not binary encoded.

How does our current VC schema compare in terms of interoperability and future-readiness with the EAS x Ceramic standards?

Answer: This depends on the future-perspective. EAS I think is very much on-chain focused, while the VC format is not (I think this is reflected also in the off-chain attestation format). If EAS however would support writing attestation into a VC format (with EIP-712 signature), interoperability easier). User could use tools like didkit (available in several languages) to validate these attestations), and attestations would still remain verifiable on-chain.

What are the implications of adopting the EAS x Ceramic schema for our migration strategy and operational continuity?

Answer: I asume this question refers to this example: https://docs.attest.sh/docs/tutorials/ceramic-storage . So, the format presented here would also get the job done, but:

  • the payload is binary-encoded (compared to cleartext in the VC)
  • VC has a better support in tooling (several providers of libraries, across multiple programming languages)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging a pull request may close this issue.

4 participants