HollowDB Prover

Utility package to generate proofs for HollowDB.

To ease proof generation, we provide a prover utility for the circuit used by HollowDB.

Usage

To generate proofs, you will need the zero-knowledge circuit WASM file, and a prover key. Both can be found within the repo, see here. Notice that there are separate files for each protocol, Groth16 and PLONK respectively.

To create the prover:

const prover = new Prover(
    "./path-to-circuit-wasm",
    "./path-to-prover-key",
    "groth16" // or "plonk"
);

Let us explain the constructor arguments in order:

  • wasmPath is the relative path to the circuit WASM file. In a web application, this file can be stored under public.

  • proverKeyPath is the relative path to the WASM circuit. In a web application, this file can be stored under public.

  • protocol is the proof system to be used, that is either groth16 or plonk. HollowDB supports both proof systems, and the verifier can determine which one to use by looking at the verification key.

To generate a proof, simply call prove function of the newly created prover:

const {proof, publicSignals} = prover.prove(PREIMAGE, CURRENT_VALUE, NEXT_VALUE);

The proof object here shall be provided to HollowDB contract, where it will be checked to verify. Note that public signals are also exported, although we do not use them; the contract obtains them in it's own ways.

The value inputs are "hashed-to-group" and then fed into the circuit. See the Hash-to-Groupsection below for more information.

For the curious, the public signals is a triple with the following elements in order:

  • Current value hash

  • Next value hash

  • Key, equal to Poseidon hash of the preimage

Prove with Hashes

The prove function takes as input two objects, and it converts them to be circuit-friendly inputs within the function. If you would like to re-use these hashes, or you simply have access to them, you can generate a proof from them too:

const {proof} = prover.proveHashed(PREIMAGE, CUR_VAL_HASH, NEXT_VAL_HASH);

Proving In NextJS

Note that to use SnarkJS in a NextJS environment you may need to configure some settings w.r.t server-side rendering. We suggest adding the following Webpack option to your NextJS config:

webpack: (config, { isServer }) => {
  if (!isServer) {
    config.resolve.alias = {
      ...config.resolve.alias,
      fs: false, // added for SnarkJS
      readline: false, // added for SnarkJS
    };
  }
  // added to run WASM for SnarkJS
  config.experiments = { asyncWebAssembly: true };
  return config;
},

You might also have to make some configurations in other frameworks if you have server-side rendering enabled.

Computing the Key without Proofs

When HollowDB is used with proofs in particular, the key is computed by taking the Poseidon hash of some secret preimage. The key can be extracted from the publicSignals which is in the object that is returned from the prove function.

However, if one wants to compute the key without creating a proof (e.g. the user just wants to get a value at their own key) they can do so with computeKey.

import {computeKey} from 'hollowdb-prover'

const key = computeKey(PREIMAGE);

Hash-to-Group

To "embed" the current value and next value within our proofs, we need to map them to a number. This number must be circuit-friendly (to be more technical, it must be within the scalar field of the curve used in our circuit, which is alt_bn128).

We provide a hashToGroup function for this purpose:

import {hashToGroup} from 'hollowdb-prover'

const valueHashed = hashToGroup({foo: "bar", num: 123});

Note that the output of this function is a bigint, not a string! To store it as a string, you may use toString method of the BigInt, with an optional radix. We suggest storing these as hexadecimal strings with 0x prefix, which allows them to be converted to BigInt easily.

const valueHashedStr = '0x' + valueHashed.toString(16);

Last updated