Blazor calling SnarkJS

208 Views Asked by At

For SnarkJS (https://github.com/iden3/snarkjs), there's an HTML example showing how to consume their ES6 javascript library:

<!doctype html>
<html>
<body>

  <script src="snarkjs.min.js">   </script>
  <script>

async function calculateProof() {

    const { proof, publicSignals } =
      await snarkjs.groth16.fullProve( { a: 3, b: 11}, "circuit.wasm", "circuit_final.zkey");
      
  </script>

</body>
</html>

This call to snarkjs.groth16.fullProve works perfectly in the browser.

In Blazor, I load snarkjs.min.js into an IJSObjectReference (myJSmodule), but I don't know how to emulate the snarkjs.groth16.fullProve call from Blazor to the module. Something like:

await myJSmodule.InvokeVoidAsync("snarkjs.groth16.fullProve", args...)

but that produces

Could not find 'snarkjs.groth16.fullProve'...'snarkjs' was undefined

EDIT: In the end, I had two problems:

  1. Chrome was caching my embedded javascript (not the dynamically loaded modules) so running the app would result in it using outdated cached javascript. Solution was to long-click on the Chrome refresh button, and choosing "Empty Cache and Hard Reload". Though I'm not sure if this bodes well for deployed consumer-facing websites.

  2. Dimitris' answer below took care of the second problem.

1

There are 1 best solutions below

5
Dimitris Maragkos On BEST ANSWER

You can create a helper js module that exports the calculateProof function:

snarkJsInteropHelper.js

export async function calculateProof() {
    const { proof, publicSignals } =
        await snarkjs.groth16.fullProve({ a: 3, b: 11 }, "circuit.wasm", "circuit_final.zkey");
}

Then in blazor component:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        var module = await JS.InvokeAsync<IJSObjectReference>(
          "import", "./snarkJsInteropHelper.js");

        await module.InvokeVoidAsync("calculateProof");
    }
}