Skip to content

ukstv/skyward

Repository files navigation

Skyward

Skyward reduces compilation time of a O1JS ZK program on Web.

Skyward allows you to pre-cache artifacts like prover keys, verification keys, SRS, and so on. With that ZK program compilation takes just a few seconds.

Check out the demo at https://skyward.run. The code for it is in examples/example-vite folder.

You could see pre-cached compilation is 2-5x faster, on mobile and desktop. After you refresh the page, the improvement is about 15x on mobile, which is considerable for a repeat user. More complex ZK program you have, more the difference is.

Installation

Add skyward as a dependency using npm, pnpm or yarn:

npm add skyward

Usage

Before the artifacts can be used for pre-caching, they have to be made available on the Web.

1. Compiling the program and preparing the artifacts locally

Create a script that prepares the artifacts. Let's say you compile HelloProgram:

// scripts/compile.ts
import { prepare } from "skyward/prepare";
import { HelloProgram } from "../src/hello-program.js";

await prepare(HelloProgram);

Run it, for example using tsx:

tsx scripts/compile.ts

That would make the artifacts known for skyward. You could see that if you list the known programs:

npx skyward list

For example-vite and HelloProgram it outputs:

┌───────────────┬──────────────────────────────────────────────┬───────┬──────────┐
│ Name          │ Hash                                         │ Files │ Size     │
├───────────────┼──────────────────────────────────────────────┼───────┼──────────┤
│ hello-program │ uJS7R9Qnl78lcuvLU7yVsZaAVYD_otIMyBjj8G2XV42I │ 10    │ 15.97 MB │
└───────────────┴──────────────────────────────────────────────┴───────┴──────────┘

2. Create skyward account

You should create an account to upload the artifacts on skyward cloud. See Cloud section for rationale.

npx skyward login

3. Upload the artifacts

After the artifacts are uploaded, skyward will create a JSON manifest file skyward.json. It is used to pre-cache all the necessary artifacts for a program when in browser.

We expect the file to be located in src/data/skyward.json. We pass the folder to the command:

npx skyward upload src/data

If you have multiple programs, and you intend to upload just specific programs:

npx skyward upload src/data -p program1 -p program2

4. Use ZK program in a browser

Now you should tell O1JS to use a pre-populated cache. Let's assume you have a vanilla code like this:

import { HelloProgram } from "../hello-program.js";
import { expose } from "comlink";

const functions = {
  async compile() {
    await HelloProgram.compile();
  },
};

expose(functions);

It should be changed to look like this:

import { HelloProgram } from "../hello-program.js";
import { expose } from "comlink";
import { RemoteCache, decode, ManifestContent } from "skyward/browser";
import * as manifestJSON from "../data/skyward.json";

// Instantiate a cache from the manifest file
const cache = RemoteCache.fromManifest(decode(ManifestContent, manifestJSON));
// Promise that resolves when we are done pre-caching the artifacts
const precacheP = cache.populate(HelloProgram.name);

const functions = {
  async compile() {
    await precacheP;
    await HelloProgram.compile({ cache: cache });
  },
};

expose(functions);

See, we pass our custom cache to HelloProgram.compile. The cache gets pre-populated by the artifacts listed in manifestJSON you created on a previous step. To ensure it has all the artifacts, we wait (await precacheP) until the pre-caching is done.

Cloud

You could host the artifacts along with the rest of your webapp bundle. It means though, you have to build them before the bundling, or store them in a repository. Or, you could use your own blob storage - Amazon S3, GCP Storage, Vercel Blobs, etc. We found it to be quite inconvenient: manage automation, proper caching, getting big repos, manage HTTP headers. We decided to make the experience more comfortable.

Commands

You could see all the commands available running

npx skyward --help
  • adduser - Add a user account, asks for email and password
  • login - Login to the account, asks for email and password
  • logout - Clear locally stored access token for the logged in user
  • whoami - Show an email of a user currently logged in
  • list - List known ZK programs of the project
  • upload - Upload ZK program artifacts to the cloud
  • serve - Serve program artifacts over HTTP locally, uses port 4040 by default
  • extract - Similar to upload, but copies the artifacts to the target folder

The last two commands are worth describing in more detail.

serve: During local development, you might want to avoid cloud. You might consume locally-served artifacts. We could adapt our familiar HelloProgram example by changing cache variable:

// Instantiate a cache from the manifest file served at http://localhost:4040/skyward.json
// This is default by `skyward serve`
const cache = RemoteCache.fromManifestURL();

extract: Useful in case you want to host the artifacts by yourself. It generates a manifest JSON file same as upload, and copies the artifacts to the destination folder of your choosing.

npx skyward extract src/data

That would create the artifacts at src/data folder, and src/data/skyward.json manifest file that references those. The manifest file could be used as shown above.

Maintainers

@ukstv

Contributing

Feel free to dive in! Open an issue, submit PRs, ask questions, make suggestions.

License

MIT OR Apache-2.0

About

Reduce compilation time of a O1JS ZK program on Web

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published