Proofs from Signatures
Generating Proofs via NextJS + Injected Wallet.
When HollowDB is used together with a dApp, we have the perfect opportunity to use zero-knowledge proofs by making use of the user wallet. In particular, we can derive a secret at client-side using the user wallet, and then generate our key from that derived secret. Here is an example flow for such a use-case:
Secret: A signature on a pre-determined a constant string, signed by users for your dApp
Preimage: the secret hashed to a group element (i.e. a circuit-friendly value)
Key: A key derived from the preimage using Poseidon hash (i.e. a zk-friendly hash function)
To try this flow yourself, you can quickly get started with a dApp boilerplate and follow this guide. We think Rainbowkit provides a really simple boilerplate dApp where you can connect your wallet, so start by setting up the scaffold code described at Rainbowkit quickstart.
We don't really need anything other than the wallet connection button here, so go ahead to index.tsx
and change the component to the following:
We will make use of our prover utility class, so let us install it too:
Then, make sure you configure Webpack options, describe at the section: Proving In NextJS.
Getting the Signature
The first thing we have to do is obtain the user signatures for some string. To do so, add the following to within the component:
useSignMessage
is a hook exported by Wagmi, which Rainbowkit wraps around. When we call signMessage
, it will cause for instance MetaMask to pop-up and ask for user to sign a message.
Let's add a tiny button to get that signature, just below <ConnectButton />
we will add:
We have added a tiny style to our button as well, if you would like to add within your Home.module.css
:
Hashing the Signature
We can hash this signature to a circuit-friendly value; or in a bit more technical term: we can do a hash-to-group operation where the result of hash must conform to some rules. In the simplest case, the resulting digest must be smaller than some value (order of the group).
Our HollowDB Prover utility class provides a hash-to-group function:
Then we add a useMemo
to calculate this hash whenever signature changes.
We will use this preimage
when we are creating zero-knowledge proofs for HollowDB.
You are free to use any other method for the hashing-to-group part, all you have to do is make sure that the resulting digest corresponds to a number that is less than:
For the curious, that is the order of the scalar field of BN254 curve, which is the finite field that our circuit operates on.
Generating the Proof
Our utility package also exports a prover class: Prover
. It is really straightforward to use, you just have to provide paths to the WASM circuit and prover key files. These files can be stored under public
directory. You can download them from HollowDB repository.
Import our Prover above:
Let's add our button that will generate the proofs, right inside the same div
with the previous button
:
You can see how the Prover
object is created by providing the paths to WASM circuit and the prover key. Then, we simply call the prove
function with the preimage, current value and the next value.
The value inputs are "hashed-to-group" and embed within the proof itself, this logic is handled within the function.
Computing the Key
Can we compute the key without generating a proof? Yes, we have the computeKey
function for that!
We can add another useMemo
to calculate this final hash whenever the previous hash changes.
The client can use this key
to read values from HollowDB, without needing to generate proofs.
Putting it All Together
Here is how index.tsx
looks like in the end:
You should see something like this in the middle of the screen when you connect your wallet:
Last updated