Skip to content

Commit

Permalink
improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyjfpender committed Aug 8, 2023
1 parent 08fba81 commit 2a5672e
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 29 deletions.
4 changes: 3 additions & 1 deletion apps/docs/pages/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
},
"index": "Herald",
"introduction": "Introduction",
"ideas": "Key Ideas",
"architecture": "Architecture",
"why": "Why",
"future": "Future Features",
"---": {
"type": "separator",
"title": "Build on Herald"
},
"benchmarks": "Benchmarks",
"build": "Get started",
"build": "Get Started",
"config": "Configure",
"tools": "Tooling",
"ecosystem": "Ecosystem",
Expand Down
111 changes: 101 additions & 10 deletions apps/docs/pages/architecture.mdx
Original file line number Diff line number Diff line change
@@ -1,25 +1,116 @@
import { Callout } from 'nextra-theme-docs'

# 1) First title
# The Herald Stack

## 2) Second title
Herald is a thin wrapper around SnarkyJS. Herald currently has three layers:
- [**@herald-sdk/data-model**](#herald-sdkdata-model) - this package provides classes and utilities for managing claims, signed claims, and other data structures relevant to Zero-Knowledge Proofs and their associated cryptographic functions.
- [**@herald-sdk/provable-programs**](#herald-sdkprovable-programs) - this package provides a single `ZkProgram` that allows users to attest to their credentials per some `Rule` provided by a challenger.
- [**@herald-sdk/credentials**](#herald-sdkcredentials) - this package encapsulates both `data-model` and `provable-programs` packages, allowing issuers to create credentials, subjects to attest to claims about their credentials, and verify if a credential was issued by a specific issuer and about a specific subject.

## 3) Third title
## `@herald-sdk/data-model`

## 4) Fourth title
### Modules

#### `dataModel.ts`

## The Herald Stack
##### Class: `Claim`
A claim is a `MerkleMap` of key-value pairs where the key is a string and the value is a `ClaimType`. It provides methods to add, get, and retrieve the Merkle root and witness for a given key.

For now, let's focus on the high level overview and scrap the surface of each of these layers.
- `addField(key: string, value: ClaimType)`: Adds a field to the claim's `MerkleMap`.
- `getField(key: string): Field | undefined`: Gets the Field corresponding to the provided key.
- `getRoot()`: Field: Returns the Merkle root of the claim's `MerkleMap`.
- `getWitness(key: string): MerkleMapWitness`: Retrieves the MerkleMapWitness for a given key.

![stack](../static/img/stack.png)

### Creating credentials
##### Class: `SignedClaim`
A signed claim is a claim that has been signed by an issuer. It contains the root of the claim and the signature of the issuer.

### Proving statements about credentials
##### Class: `CredentialPresentation`
A structure that attests to being the owner of a credential, useful for Zero-Knowledge Proofs.

##### Class: `Rule`
A rule that can be used to infer a claim from another claim. It can be provided by a challenger to a prover to verify a property on a claim.

#### `types.ts`

##### Type: `ClaimType`
Defines the possible data types for a claim. It can be a string, number, or a PublicKey.

#### `utils/construction.ts`
Utility functions to construct various data structures.
- `constructClaim(claims: {[key: string]: ClaimType}): Claim`: Constructs a claim from a dictionary of claims.
- `constructSignedClaim(claim: Claim, issuerPrvKey: PrivateKey): SignedClaim`: Constructs a signed claim.
- `constructPresentation(signedClaim: SignedClaim, subjectPrvKey: PrivateKey): CredentialPresentation`: Constructs a credential presentation from a signed claim.

#### `utils/conversion.ts`
Utility functions for converting between various data structures.
- `stringToField(str: string): Field`: Converts a string to a Field.
- `numberToField(num: number): Field`: Converts a number to a Field.
- `publicKeyHash(publicKey: PublicKey): Field`: Hashes a PublicKey to produce a Field.
- `claimToField(claim: ClaimType): Field`: Converts a claim to a Field.
- `fieldToString(field: Field[]): string`: Converts a Field to a string.
- `flattenObject(obj: {[key: string]: any}, prefix = ''): {[key: string]: ClaimType}`: Flattens an object into a dictionary of claims.

## Usage
The `@herald-sdk/data-model` package allows users to create and manage claims and their associated cryptographic proofs. With utilities for constructing and converting these data structures, developers can effortlessly integrate Zero-Knowledge Proofs and cryptographic functions into their applications.

## `@herald-sdk/provable-programs`

### Modules

#### `ChallengeProgram.ts`

##### Class: `PublicInputArgs`
This class defines the public inputs for the Zero-Knowledge Program (ZkProgram). These inputs include the public keys of the issuer and subject, as well as a rule (`provingRule`) for attesting the credentials.

##### `AttestCredentials`
This is a Zero-Knowledge Program (ZkProgram) that works to validate a claim on a credential. The current implementation works for one field on a claim. It has a single `attest` method and requires `PublicInputArgs`.

- `attest`: This method validates the legitimacy of the signed claim, the credential presentation, and the correctness of the claim value based on a provided rule. It uses the public inputs to ensure that signatures are valid and the claim is correctly attested.

<Callout type="default" emoji="🧩">
One of the best features Herald offers thanks to being built with SnarkyJS is immediate integration with existing TypeScript applications. You can read more about it [here](https://docs.minaprotocol.com/zkapps/snarkyjs).
Note: Future enhancements include expanding it to work for multiple fields on a claim using a rollup style methodology.
</Callout>

## `@herald-sdk/credentials`

### Modules

#### `credential.ts`

##### Type: `proveReturnType`
The return type for the prove method in the `Credential` class. Contains:
- `attestationProof`: Proof that attests to certain claims.
- `verificationKey`: A string that represents the key used for verification.

##### Class: `Credential`
This class represents a digital credential containing a `MerkleMap` of claims (claim), a signed version of that map (`signedClaim`), and a dictionary of claims (`credential`).

###### Constructor:
- Parameters:
- `claim`: A MerkleMap representing claims.
- `signedClaim`: A signed version of the claim by the issuer.
- `credential`: A dictionary of claims.


###### Static Method: `create`
Description: An Issuer can construct a `Credential` object by taking in a dictionary of claims and a private key from the issuer.
- Parameters:
- `claims`: A dictionary representing multiple claims.
- `issuerPrvKey`: The private key of the issuer.


###### Method: `verify`
Description: Verifies the authenticity of the `Credential` object based on the given issuer and subject public keys.
- Parameters:
- `issuerPubKey`: The public key of the issuer.
- `subjectPubKey`: The public key of the subject (credential holder).


###### Method: `prove`
Description: A subject can produces a Zero-Knowledge Proof that attests to a certain claim within the credentials per a given `Rule` from a challenger.
- Parameters:
- `claimKey`: A string representing the key of the claim to attest.
- `issuerPubKey`: The public key of the issuer.
- `rule`: The rule used to create the attestation.
- `subjectPrvKey`: The private key of the subject (credential holder).
8 changes: 5 additions & 3 deletions apps/docs/pages/benchmarks.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Steps } from 'nextra-theme-docs'
import { Steps, Callout } from 'nextra-theme-docs'

import ProvingTimeAreaChart from '../components/ProvingTimeAreaChart'
import VerificationTimeAreaChart from '../components/VerificationTimeAreaChart'
import ProofSizeAreaChart from '../components/ProofSizeAreaChart'
Expand All @@ -19,13 +20,14 @@ Here are the key hardware specifications of this machine:

Efficient proof generation is crucial to the interaction design of applications, especially those that rely on frequent or time-sensitive zk-SNARK proofs. Faster proving times lead to more responsive applications and better user experience. However, it's important to note that proving time can be influenced by several factors, including computational resources, circuit sizes, and the complexity of the computation being proved. Importantly proving time efficiency requirements may vary per user, a sequencer may not need blazing fast proving time, but a wallet may require proving times to be fast given user experience requirements.

**Note: The current proving time includes program compiling time.**

The chart below visualizes the trend in proving times, allowing users to understand how updates or modifications to Herald have influenced proving efficiency over time.

<div style={{ display: 'flex', justifyContent: 'center', padding: '40px 0' }}>
<ProvingTimeAreaChart />
</div>
<Callout type="default" emoji="🚨">
Note: The current proving time includes ZkProgram compiling time. Compiling time takes roughly 45 seconds. This can be improved with artifacts of the program cached for future usage..
</Callout>

## Verification Time Benchmarks

Expand Down
129 changes: 128 additions & 1 deletion apps/docs/pages/build.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,131 @@ We first need to make sure you have everything needed to complete this tutorial.
| TypeScript | latest | `npm install -g typescript` |
| snarkyjs | 0.11.* (as a peer dependency) | `npm install snarkyjs@0.11.*` |

</Steps>
### Create a credential
Let's create a credential for a subject who is 21 years old.
```ts
import { Credential } from @herald-sdk/credentials
import { PrivateKey } from "snarkyjs";
import { ClaimType } from "@herald-sdk/data-model";


// generate issuer private keys
const issuerPrvKey = PrivateKey.random();

// construct a claim about the subject
const claims: {[key: string]: ClaimType} = {
age: 21,
subject: "B62qkAqbeE4h1M5hop288jtVYxK1MsHVMMcBpaWo8qdsAztgXaHH1xq"
};

// construct a credential using the claim and the issuer private key
const credential = Credential.create(claims, issuerPrvKey);
```

### Create a `Rule`
As a challenger, you want the subject to prove they meet some requirements like whether the subject is older than 18.
```ts
import { Rule } from "@herald-sdk/data-model";

// what property of the credentials is the challenger challenging
const property = "age";
// what constraint does the subject need to prove; in this case that the "age" is greater than or equal to `value`
const operation = "gte";
// what value does the property "age" need to be greater than or equal to
const value = 18;
// create the `Rule`
const rule = new Rule(property, operation, value);
```

### Prove your credentials can satisfy this `Rule`'s constraints
As a holder of a `Credential`, a subject can prove properties about their credentials given constraints. Note: the issuer public key needs to be assigned in the `Rule` (this is a TODO).
```ts
// given a rule and an expected issuer a holder of a `Credential` can `prove` properties of their credential
const proofResponse = await credential.prove("age", "B62qn2bkAtVmN6dptpYtU5i9gnq4SwDakFDo7Je7Fp8Tc8TtXnPxfVv", rule, subjectPrvKey);
```

### Verify the Proof
As a challenger, you can verify whether the subject has satisfied your rule's constraints
```ts
import { verify } from 'snarkyjs'

// verify the proof with a verification key
verify(proofResponse.attestationProof.toJSON(), proofResponse.verificationKey)
```
</Steps>

### W3C Credential Example
As the W3C verifiable credential data model defines, these JSON objects must be flattened to use in a `MerkleMap`. We can use the `flattenObject` function in `@herald-sdk/data-model` to do this! This is what happens:

![stack](../static/img/credential_conversion.png)

A Herald is just an abstraction over a SnarkyJS `MerkleMap`!

<Steps>
### Create credential for subject
Let's create a W3C example credential for a subject who has a Bachelor's Degree.
```ts
import { Credential } from @herald-sdk/credentials
import { PrivateKey } from "snarkyjs";
import { ClaimType, flattenObject, constructClaim } from "@herald-sdk/data-model";


// generate issuer private keys
const issuerPrvKey = PrivateKey.random();
// Define the credential
const credential = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "http://example.edu/credentials/3732",
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"issuer": "https://example.edu/issuers/565049",
"issuanceDate": new Date().toISOString(),
"credentialSubject": {
"id": "did:mina:B62qkAqbeE4h1M5hop288jtVYxK1MsHVMMcBpaWo8qdsAztgXaHH1xq",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science and Arts"
}
}
}

// flatten the credential
const flattenedCredential = flattenObject(credential);

// construct a claim about the subject
const claims = constructClaim(flattenedCredential)

// construct a credential using the claim and the issuer private key
const credential = Credential.create(claims, issuerPrvKey);
```

### Construct rule
As a challenger you want to know if the credential a subject has is a Bachelor's Degree. We need a new `Rule` for this! Remember the credential's property is now a flattened object so the rule we create must check if the "credentialSubject.degree.type" property equals "BachelorDegree".

```ts
import { Rule } from "@herald-sdk/data-model";

const property = "credentialSubject.degree.type";
const operation = "eq";
const value = "BachelorDegree";

const rule = new Rule(property, operation, value);
```

### Prove that the Credential can satisfy this Rule.
As the subject and credential owner, we can now make a proof using this rule.
```ts
const proofResponse = await credential.prove("credentialSubject.degree.type", "B62qn2bkAtVmN6dptpYtU5i9gnq4SwDakFDo7Je7Fp8Tc8TtXnPxfVv", rule, subjectPrvKey);
```

### Verify the Proof
As a challenger, you can verify whether the subject has satisfied your rule's constraints and the user does have a Bachelor's Degree, without revealing other information like the type of degree was a Bachelor of Science and Arts.
```ts
import { verify } from 'snarkyjs'

// verify the proof with a verification key
verify(proofResponse.attestationProof.toJSON(), proofResponse.verificationKey)
```
</Steps>
7 changes: 7 additions & 0 deletions apps/docs/pages/future.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Callout } from 'nextra-theme-docs'

# Future Features

## Non-Reusable Proofs

## Proving multiple `Rule`s in one proof
51 changes: 51 additions & 0 deletions apps/docs/pages/ideas.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Steps, Callout } from 'nextra-theme-docs'

# Key Ideas

## Digital Identity in the Age of Herald
Identity is a cornerstone of how we interact, both in the physical and digital realms.

## What Do We Mean by Digital Identity?

Digital identity transcends just humans. It encompasses organizations, governments, entities like DAOs, Gaming legions, and even objects or bots. In Herald's context, these identities manifest as Mina's public keys (i.e. addresses), and can be either externally owned accounts or smart contracts.

### Key Concepts:

- Anything and anyone can have a digital identity.
- An individual or entity can establish and maintain multiple identities.
- Within platforms like Mina, a digital identity can manifest as a public key.
- Any identity can issue claims about another identity.
- An owner of a claim can prove statements about claims issued to them.

## Digital Claims with Herald

Just as in the traditional world where an individual or entity can make statements or claims, the same holds in the digital realm. A digital claim is a declaration or assertion made by an identity.

Often, these claims establish relationships between identities. For instance, when an online educational platform vouches that a user has completed a course, it's a digital claim linking the user and the platform.

Claims have a broad spectrum. They can be public, private, and can represent nearly any interaction or declaration. Whether it's a digital thumbs-up, an invoice, or an email, in the Herald universe, these are all claims.

### Examples of `Claims`:

- Certifications or badges earned online.
- Defeating a monster in a game.
- Leveling up a character.
- Social media interactions.
- Digital invoices.
- Email correspondences.
- Digital roles or permissions within a platform.
- Online endorsements or reviews.

## Zero-Knowledge Proofs & Herald

Modern cryptography has gifted us the concept of zero-knowledge proofs (ZKPs). It's a mechanism allowing one entity to prove to another that they possess certain knowledge, without revealing the specifics of that knowledge.

This matters because in the realm of digital claims, there are moments when we want to validate something discreetly, maintaining privacy while ensuring authenticity. The future of Web3 requires privacy as a feature not as a nice-to-have.

### Real-world Applications:

- Digital KYC Version: Imagine proving you meet the jurisdictional requirements for interacting with a zkApp without exposing any other details about yourself; proving only that you meet the requirements the zkApp requires. With ZKPs, you can validate that you possess the digital key tied to an identity that has been KYC'd, without disclosing further information.

- Anonymous Digital Voting: Just as in the offline world, there are times when you'd want to validate your eligibility to vote without unveiling your identity. ZKPs make this a reality.

By fusing time-honored concepts of identity with state-of-the-art cryptographic techniques, Herald stands at the forefront of the new digital era. Our library seeks to make these concepts accessible, ensuring that developers and users can navigate this new landscape with confidence and clarity.
2 changes: 1 addition & 1 deletion apps/docs/public/benchmarks/credential-proving.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"name":"2023-8-6","duration":263.847},{"name":"2023-8-8","duration":73.13}]
[{"name":"2023-8-8","duration":73.13}]
2 changes: 1 addition & 1 deletion apps/docs/public/benchmarks/proof-verifying.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"name":"2023-8-6","duration":6.24},{"name":"2023-8-8","duration":1.552}]
[{"name":"2023-8-8","duration":1.552}]
Binary file added apps/docs/static/img/credential_conversion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/docs/theme.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react'
import { DocsThemeConfig } from 'nextra-theme-docs'
import { useRouter } from 'next/router';



const config: DocsThemeConfig = {
logo: <span>Herald</span>,
project: {
Expand Down
Loading

0 comments on commit 2a5672e

Please sign in to comment.