//go:build js && wasm // attesto-verify-wasm [P3.1] — the verifier-only WebAssembly build. // // Exposes the offline verification functions (and nothing else: no client, // no CLI, no network capability is ever invoked) on a global // `attestoVerify` object for the docs-site /verify drop-zone. Every // function takes JSON strings and returns a JSON string, so the JS side // stays a thin shell. package main import ( "encoding/json" "syscall/js" attesto "go.attesto.eu/sdk" ) func respond(value any) string { raw, err := json.Marshal(value) if err != nil { return `{"ok":false,"problems":["internal: response marshal failed"]}` } return string(raw) } func fail(problem string) string { return respond(map[string]any{"ok": false, "problems": []string{problem}}) } // verifyReceipt(receiptJSON, publicKeyHex) -> VerifyReport JSON func verifyReceipt(_ js.Value, args []js.Value) any { if len(args) != 2 { return fail("usage: verifyReceipt(receiptJSON, publicKeyHex)") } var receipt attesto.SignedReceipt if err := json.Unmarshal([]byte(args[0].String()), &receipt); err != nil { return fail("receipt is not valid JSON: " + err.Error()) } return respond(attesto.VerifyReceiptOffline(receipt, args[1].String())) } // verifyInclusion(leafHash, proofJSON, rootHash) -> {ok, problems} func verifyInclusion(_ js.Value, args []js.Value) any { if len(args) != 3 { return fail("usage: verifyInclusion(leafHash, proofJSON, rootHash)") } var proof []attesto.InclusionStep if err := json.Unmarshal([]byte(args[1].String()), &proof); err != nil { return fail("proof is not valid JSON: " + err.Error()) } ok, err := attesto.VerifyInclusionProof(args[0].String(), proof, args[2].String()) if err != nil { return fail(err.Error()) } return respond(map[string]any{"ok": ok, "problems": []string{}}) } // verifyCheckpointRoot(windowHashesJSON, expectedRoot) -> {ok, problems} func verifyCheckpointRoot(_ js.Value, args []js.Value) any { if len(args) != 2 { return fail("usage: verifyCheckpointRoot(windowHashesJSON, expectedRoot)") } var hashes []string if err := json.Unmarshal([]byte(args[0].String()), &hashes); err != nil { return fail("windowHashes is not valid JSON: " + err.Error()) } ok, err := attesto.VerifyCheckpointRoot(hashes, args[1].String()) if err != nil { return fail(err.Error()) } return respond(map[string]any{"ok": ok, "problems": []string{}}) } // verifyCompleteness(eventsJSON, fromSeqNo, toSeqNo) -> VerifyReport JSON func verifyCompleteness(_ js.Value, args []js.Value) any { if len(args) != 3 { return fail("usage: verifyCompleteness(eventsJSON, fromSeqNo, toSeqNo)") } var events []map[string]any if err := json.Unmarshal([]byte(args[0].String()), &events); err != nil { return fail("events is not valid JSON: " + err.Error()) } return respond(attesto.VerifyCompleteness(events, args[1].Int(), args[2].Int())) } func main() { exports := js.Global().Get("Object").New() exports.Set("verifyReceipt", js.FuncOf(verifyReceipt)) exports.Set("verifyInclusion", js.FuncOf(verifyInclusion)) exports.Set("verifyCheckpointRoot", js.FuncOf(verifyCheckpointRoot)) exports.Set("verifyCompleteness", js.FuncOf(verifyCompleteness)) exports.Set("sdkVersion", attesto.SDKVersion) js.Global().Set("attestoVerify", exports) // Keep the runtime alive for calls from JS. select {} }