Native backend
NativeBackend (src/native-backend.ts) is a Node-only thin wrapper that shells out to the compiled ecdsa-spartan2 Rust CLI. Use it when:
- you want to run
prepare setup/show setup(the WASM bridge cannot do setup); - you have proving keys too large for browser memory (≥ 258 MB for the
1kvariant); - you need parity with the CI / benchmark pipeline that lives under
wallet-unit-poc/ecdsa-spartan2/.
It is not loaded by OpenAC.init and adds no dependencies for browser bundles — import the class directly:
import { NativeBackend } from "openac-sdk";
const native = new NativeBackend({ workDir: "wallet-unit-poc/ecdsa-spartan2" });
If binaryPath or workDir are omitted, NativeBackend searches relative paths from the SDK install location and process.cwd(). It throws SetupError("KEYS_NOT_FOUND") when neither resolves.
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
binaryPath | string | First match of target/release/ecdsa-spartan2 near the SDK or in cwd(). | Absolute path to the compiled CLI binary. |
workDir | string | First directory containing Cargo.toml near the SDK or in cwd(). | Directory the CLI runs in (keys, artifacts and inputs are resolved relative to it). |
inputDir | string | ${workDir}/../circom/inputs | Where the input JSONs live (jwt/<size>/default.json, show/default.json). |
env | Record<string, string> | RUST_LOG=info plus auto-detected DYLD_LIBRARY_PATH for the witnesscalc dylib. | Extra env vars merged into the child process. |
Lifecycle
const native = new NativeBackend();
await native.setup("wallet-unit-poc/circom/inputs/jwt/1k/default.json");
await native.proveAll(
"wallet-unit-poc/circom/inputs/jwt/1k/default.json",
"wallet-unit-poc/circom/inputs/show/default.json",
);
const { valid } = await native.verifyPrepare();
| Method | CLI command run | Default timeout | Notes |
|---|---|---|---|
setupPrepare(inputPath?) | prepare setup | 20 min | Writes keys/prepare_*.key. |
setupShow(inputPath?) | show setup | 10 min | Writes keys/show_*.key. |
setup(inputPath?) | both | 30 min | Convenience for one-shot setup. |
provePrepare(inputPath?) | prepare prove | 5 min | Reads prepare_proving.key, writes prepare_proof.bin, prepare_instance.bin, prepare_witness.bin. |
proveShow(inputPath?) | show prove | 2 min | Reads show_proving.key, writes show_* artifacts. |
generateSharedBlinds() | generate_shared_blinds | 10 min | Writes keys/shared_blinds.bin. |
reblindPrepare() / reblindShow() | prepare reblind / show reblind | 5 min / 2 min | Applies the shared blinds. |
verifyPrepare() / verifyShow() | prepare verify / show verify | 10 min | Returns { valid, output } based on a substring check for "Verification successful". |
runBenchmark(inputPath?) | benchmark | 30 min | Captures stdout/stderr for the benchmark harness. |
proveAll(jwtInputPath?, showInputPath?) | composite of the above | inherited | generate_shared_blinds → prove prepare → reblind prepare → prove show → reblind show. |
Artifacts
NativeBackend.loadKeys() reads the four *.key files into a KeySet compatible with OpenAC.precompute / OpenAC.present. loadProofs() returns the proof, instance, witness, and shared-blind bytes — useful for transporting Rust-generated artifacts into the WASM verifier.
saveArtifact(filename, data) / loadArtifact(filename) are escape hatches for custom file layouts; they read and write under ${workDir}/keys/.
The keysExist and proofsExist getters do a non-throwing existence check before attempting a CLI command.
Errors
| Failure | Thrown |
|---|---|
| Binary or workDir not found at construction time | SetupError("KEYS_NOT_FOUND") |
| Non-zero exit from any CLI invocation | ProofError("PROOF_GENERATION_FAILED") with cause set to the underlying execFile error. |
The output field on verifyPrepare() / verifyShow() returns the combined stdout+stderr; the CLI prints Verification successful on success, which is the substring NativeBackend looks for.