diff --git a/Cargo.lock b/Cargo.lock index b830dc0..c0277f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -145,8 +151,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -182,6 +190,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -197,6 +214,12 @@ version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "memchr" version = "2.7.4" @@ -231,6 +254,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -386,6 +415,7 @@ dependencies = [ name = "snark-bn254-verifier" version = "1.0.2" dependencies = [ + "getrandom", "lazy_static", "num-bigint", "num-traits", @@ -393,6 +423,7 @@ dependencies = [ "sha2", "substrate-bn", "thiserror", + "wasm-bindgen", ] [[package]] @@ -524,6 +555,61 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + [[package]] name = "winnow" version = "0.6.18" diff --git a/README.md b/README.md index c169343..cd51d15 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,20 @@ fn main() { ``` +#### Compile to WASM +Build the wasm module with the following command: +```bash +cd verifier +wasm-pack build --target nodejs --dev # adjust the target to your liking +``` + +Then run the example in the `examples/wasm_example` directory: +```bash +cd examples/wasm_example +pnpm install +pnpm run test +``` + ## Features - Verification of Groth16 and PlonK proofs generated using `gnark` or `sp1` on the `Bn254` curve. diff --git a/examples/README.md b/examples/README.md index f702d6d..df0fedb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,21 +1,21 @@ # Examples This is a simple example of how to use the `snark-bn254-verifier` crate to verify a proof generated by the `SP1` library. The cycle count for running the programs varies depending on the proof system used: -| Program | Plonk Proof | Groth16 Proof | -|----------------|----------------|---------------| -| Fibonacci | 8,078,761 | 9,656,158 | -| Is-Prime | 8,050,250 | 9,651,061 | -| Tendermint | 8,044,765 | 9,653,857 | -| SHA-2 | 8,078,621 | 9,637,958 | +| Program | Plonk Proof | Groth16 Proof | +| ---------- | ----------- | ------------- | +| Fibonacci | 8,078,761 | 9,656,158 | +| Is-Prime | 8,050,250 | 9,651,061 | +| Tendermint | 8,044,765 | 9,653,857 | +| SHA-2 | 8,078,621 | 9,637,958 | To run the example, you can use the following ELF options: -| ELF Option | Description | -|----------------|------------------------------------| -| fibonacci | Fibonacci sequence program | -| is-prime | Prime number checking program | -| sha2 | SHA-2 hashing program | -| tendermint | Tendermint consensus program | +| ELF Option | Description | +| ---------- | ----------------------------- | +| fibonacci | Fibonacci sequence program | +| is-prime | Prime number checking program | +| sha2 | SHA-2 hashing program | +| tendermint | Tendermint consensus program | To run the example, run the following command: ```bash @@ -26,5 +26,21 @@ cargo prove build --bin groth16 # Run the example cd ../script +cargo build # Installs the circuit artifacts RUST_LOG=info cargo run --release -- --elf fibonacci --mode plonk +``` + +### Wasm Example + +To build the JSON proofs for the wasm example, run the following command: +```bash +cd script +cargo build +``` + +To run the wasm example, run the following command: +```bash +cd wasm_example +pnpm install +pnpm run test ``` \ No newline at end of file diff --git a/examples/script/Cargo.lock b/examples/script/Cargo.lock index 189b386..5644db4 100644 --- a/examples/script/Cargo.lock +++ b/examples/script/Cargo.lock @@ -3828,13 +3828,13 @@ dependencies = [ "hex", "num-bigint 0.4.6", "num-traits", + "serde_json", "snark-bn254-verifier", "sp1-helper", "sp1-prover", "sp1-sdk", "strum 0.25.0", "strum_macros 0.25.3", - "substrate-bn", ] [[package]] @@ -4614,6 +4614,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" name = "snark-bn254-verifier" version = "1.0.2" dependencies = [ + "getrandom", "lazy_static", "num-bigint 0.4.6", "num-traits", @@ -4621,6 +4622,7 @@ dependencies = [ "sha2", "substrate-bn", "thiserror", + "wasm-bindgen", ] [[package]] diff --git a/examples/script/Cargo.toml b/examples/script/Cargo.toml index 100c1f6..4a19fe1 100644 --- a/examples/script/Cargo.toml +++ b/examples/script/Cargo.toml @@ -16,7 +16,9 @@ strum_macros = "0.25" [build-dependencies] sp1-helper = "2.0.0" +sp1-prover = "2.0.0" +sp1-sdk = "2.0.0" +serde_json = "1.0.128" [dev-dependencies] snark-bn254-verifier = { path = "../../verifier" } -substrate-bn = { git = "https://github.com/sp1-patches/bn", branch = "patch-v0.7.0" } diff --git a/examples/script/build.rs b/examples/script/build.rs new file mode 100644 index 0000000..7bba7ff --- /dev/null +++ b/examples/script/build.rs @@ -0,0 +1,27 @@ +use sp1_sdk::install::try_install_circuit_artifacts; +use sp1_sdk::SP1ProofWithPublicValues; +use std::fs; +use std::path::Path; + +fn main() { + // Install the Groth16 and Plonk circuit artifacts + try_install_circuit_artifacts(); + + let binaries_dir = Path::new("../binaries"); + let output_dir = Path::new("../wasm_example/data"); + + // Convert binary proofs to JSON + fs::read_dir(binaries_dir) + .expect("Failed to read binaries directory") + .filter_map(Result::ok) + .filter(|entry| entry.path().extension().and_then(|s| s.to_str()) == Some("bin")) + .for_each(|entry| { + let path = entry.path(); + let proof = SP1ProofWithPublicValues::load(&path).expect("Failed to load proof"); + let json_proof = serde_json::to_string(&proof).expect("Failed to serialize proof"); + let json_path = output_dir + .join(path.file_stem().unwrap()) + .with_extension("json"); + fs::write(json_path, json_proof).expect("Failed to write JSON proof"); + }); +} diff --git a/examples/script/src/main.rs b/examples/script/src/main.rs index b575b3d..73bde07 100644 --- a/examples/script/src/main.rs +++ b/examples/script/src/main.rs @@ -171,9 +171,8 @@ mod tests { use super::*; - use snark_bn254_verifier::{Groth16Verifier, PlonkVerifier}; + use snark_bn254_verifier::{Fr, Groth16Verifier, PlonkVerifier}; use strum::IntoEnumIterator; - use substrate_bn::Fr; const PLONK_VK_BYTES: &[u8] = include_bytes!("../../../../.sp1/circuits/v2.0.0/plonk_vk.bin"); const GROTH16_VK_BYTES: &[u8] = diff --git a/examples/wasm_example/data/fibonacci_groth16_proof.json b/examples/wasm_example/data/fibonacci_groth16_proof.json new file mode 100644 index 0000000..d5231f9 --- /dev/null +++ b/examples/wasm_example/data/fibonacci_groth16_proof.json @@ -0,0 +1 @@ +{"proof":{"Groth16":{"public_inputs":["338694232377558529823153776359654126084495984661914661651706714220115668510","6835433473072582537735779005252378178401920886001391083506222100041177144720"],"encoded_proof":"073862c903a173089485c6916e7d55d31826104842e002548028443932b13021100cdab28507e0d1415a29853f9e930f477c1af99e60c1f758fa9faf316a9e8b07d1e42c7d4f44b3f042caae815840be2e31aad122ce512c17a17b79f954bf9f0736236acb8c29084781c26fac901f0573927af9b99f94cc0b2344cbad12c0d406b24aeaf4c3eb34e96e9e11544da04e2f950d13923c8e3002fc6022a99419db0787dc86be057118d5ed953377b49120040d6514450462c04d22d637bfa1d84d19bb0e4e33a31f09313c1a9f7548ea66e09dbd36af5329dc2c43c73de9314b9a203338ae4a62d5e8eb6932bac4eaa09ff2381f9aa459b7748b35d3c714a5ec6e","raw_proof":"073862c903a173089485c6916e7d55d31826104842e002548028443932b13021100cdab28507e0d1415a29853f9e930f477c1af99e60c1f758fa9faf316a9e8b07d1e42c7d4f44b3f042caae815840be2e31aad122ce512c17a17b79f954bf9f0736236acb8c29084781c26fac901f0573927af9b99f94cc0b2344cbad12c0d406b24aeaf4c3eb34e96e9e11544da04e2f950d13923c8e3002fc6022a99419db0787dc86be057118d5ed953377b49120040d6514450462c04d22d637bfa1d84d19bb0e4e33a31f09313c1a9f7548ea66e09dbd36af5329dc2c43c73de9314b9a203338ae4a62d5e8eb6932bac4eaa09ff2381f9aa459b7748b35d3c714a5ec6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","groth16_vkey_hash":[106,41,6,172,110,196,97,200,202,205,91,53,87,21,127,89,49,123,213,114,229,123,200,37,57,117,170,245,197,172,180,136]}},"stdin":{"buffer":[[20,0,0,0]],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,194]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/fibonacci_plonk_proof.json b/examples/wasm_example/data/fibonacci_plonk_proof.json new file mode 100644 index 0000000..9a2bb93 --- /dev/null +++ b/examples/wasm_example/data/fibonacci_plonk_proof.json @@ -0,0 +1 @@ +{"proof":{"Plonk":{"public_inputs":["338694232377558529823153776359654126084495984661914661651706714220115668510","6835433473072582537735779005252378178401920886001391083506222100041177144720"],"encoded_proof":"2448be9e53902e783637964863ddb1eba8c718091b9d4c6cc88c6b7e11f926d62754b8254411fcbb1a7f8e3c05de5c85aef24e3ab1091da1c90694557711df080ba315037d36a917d61ceca92465e51ee7489ac51115fa78fc5ec426a21c4f7715b1d6f3ee87e32c9cdf212159ca4276a7e018c1d9982ef60888a34c0bc9e34a045c6a62e1cdeac6b7f74774e909c9fdc96cad62700348f7c0965d447cd47041187a282676b9a3fcb08be36a9ae3cd05827420f69fc560319e931514777ed8891852b342a17af9b235939b7a4dc1658fcfcf44bf0b57db59066b513e168064742cbc8e537ffc7790f9ba77c4dd1898490ee067a5c18f38735b2f451f1a4e23f5053dcfefeadec87c9bc93be1f84a88f9435b9d4b114fd3a5bc9b9eb266f73b87211c8f184eafcc4986f6292652edc268157d24e3d50587638151b9766dd0be962d021e48ebc6ae02563f867817504e334f495e715d7a940824544d706bd52c4c17e88621d787978cc3862b91536b2daf3b1f7ff61b5e276a022d8e4ce70362251c6b31a7417b62984ccde65319ae59723d07c2e8d72e1f5c568a7b684bf57f001e2eea86a60d6b07db097993227de30fa7da8f8535afb504abe761ddda97f1271a2e3725fce3b0ad91cf9301ac7ae97c1cdff9b964bba65b4746c1c1794be02a14caa2e3ab32aca1362c923f6d37eaa9ab7fe142c9956f73fb55e6d569f213f51ac1c24da2227d47d28ef3b9b9e44e7a69e8ad53b1aeb109661813dfbd315f56143c0cb8201bcde2ae44302884470a952d62a17d9ef6778f0484b534f1634da11a2aaa8dba0524f16fb177f773f74f8379ac155af2318f8b4120c6ad1658dd0522419736f346c47a0c4570e77841abf6cdca65747b68896df6c68d3bba4a00341970fbd41886242b172b38cd0ceb510cdbd789fa9c5540c82c23dfbb5ae339e82fe1939520387479e175d0b36df61bee9ec15dd1efccb00c51e88aa51e7c1bfd1abcc37c0019a580bcf29bf2080665394de1f86536f19aa2fa224b8a87b86c2523c446901aa09b6206f030b51f58cb371605df4e3e9260776d145b15acba332708c490a519d108c323a75785a4c6a17610e114c5e8dda1d39b19784ab0fca84b00e5612ef73c019f0cbc6c568657da4e4dd9677767d72848c68b5445ff96c9fa2c17675989378ce516467bc5914225c4fe862a8ac83e71c72aaab604dd77a6e1","raw_proof":"2448be9e53902e783637964863ddb1eba8c718091b9d4c6cc88c6b7e11f926d62754b8254411fcbb1a7f8e3c05de5c85aef24e3ab1091da1c90694557711df080ba315037d36a917d61ceca92465e51ee7489ac51115fa78fc5ec426a21c4f7715b1d6f3ee87e32c9cdf212159ca4276a7e018c1d9982ef60888a34c0bc9e34a045c6a62e1cdeac6b7f74774e909c9fdc96cad62700348f7c0965d447cd47041187a282676b9a3fcb08be36a9ae3cd05827420f69fc560319e931514777ed889143c0cb8201bcde2ae44302884470a952d62a17d9ef6778f0484b534f1634da11a2aaa8dba0524f16fb177f773f74f8379ac155af2318f8b4120c6ad1658dd051852b342a17af9b235939b7a4dc1658fcfcf44bf0b57db59066b513e168064742cbc8e537ffc7790f9ba77c4dd1898490ee067a5c18f38735b2f451f1a4e23f5053dcfefeadec87c9bc93be1f84a88f9435b9d4b114fd3a5bc9b9eb266f73b87211c8f184eafcc4986f6292652edc268157d24e3d50587638151b9766dd0be962d021e48ebc6ae02563f867817504e334f495e715d7a940824544d706bd52c4c17e88621d787978cc3862b91536b2daf3b1f7ff61b5e276a022d8e4ce70362251970fbd41886242b172b38cd0ceb510cdbd789fa9c5540c82c23dfbb5ae339e82fe1939520387479e175d0b36df61bee9ec15dd1efccb00c51e88aa51e7c1bfd0000000712567003ecc599076053a3bd44d8dd9a623926b97d5758fbf93d7dad65859bc11c6b31a7417b62984ccde65319ae59723d07c2e8d72e1f5c568a7b684bf57f001e2eea86a60d6b07db097993227de30fa7da8f8535afb504abe761ddda97f1271a2e3725fce3b0ad91cf9301ac7ae97c1cdff9b964bba65b4746c1c1794be02a14caa2e3ab32aca1362c923f6d37eaa9ab7fe142c9956f73fb55e6d569f213f51ac1c24da2227d47d28ef3b9b9e44e7a69e8ad53b1aeb109661813dfbd315f5608c490a519d108c323a75785a4c6a17610e114c5e8dda1d39b19784ab0fca84b1abcc37c0019a580bcf29bf2080665394de1f86536f19aa2fa224b8a87b86c2523c446901aa09b6206f030b51f58cb371605df4e3e9260776d145b15acba332722419736f346c47a0c4570e77841abf6cdca65747b68896df6c68d3bba4a00340000000100e5612ef73c019f0cbc6c568657da4e4dd9677767d72848c68b5445ff96c9fa2c17675989378ce516467bc5914225c4fe862a8ac83e71c72aaab604dd77a6e1","plonk_vkey_hash":[74,202,36,10,62,82,150,230,165,101,249,141,199,40,198,244,143,141,228,121,42,143,163,101,3,140,59,134,149,33,118,245]}},"stdin":{"buffer":[[20,0,0,0]],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,194]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/is-prime_groth16_proof.json b/examples/wasm_example/data/is-prime_groth16_proof.json new file mode 100644 index 0000000..85a3f2e --- /dev/null +++ b/examples/wasm_example/data/is-prime_groth16_proof.json @@ -0,0 +1 @@ +{"proof":{"Groth16":{"public_inputs":["79974752685130133349989020271128338092086594955138314388631360057283056061","5408444369343130360314198614562428875014335023761526637751134529685417182618"],"encoded_proof":"06cbb8db6d4579709f5dea5016e34b1d14e931a709add4af2cf2d43bff57791e2d14247e8518a002a9b504c2bce69a25a26ab61948dcbec8789d358f46ce56010aa81d641f5a96fff0fa5cafd1b1d459c3972f90aa5dfaf6569f471c3113d65c187ae3a30bc5ce5c483a9a06fc1736990d4e03705d5a96a1b5103965ca7cb6a00c95bdf8e88c9dc1f2326c95af236f1f68146de2c7cd589a40e91a5b626b5061000b7c6d9acdccba01f8aa7cad17576315f031d9c3050a409c0354c3d90a170727aa69b8b70d6e30089b3152bbc1c4924b981cb06718afcd48e6111e94772545133a5e8ab0a3772d78635e169a3e91d7c8c0389523e7f15089714818326d708c","raw_proof":"06cbb8db6d4579709f5dea5016e34b1d14e931a709add4af2cf2d43bff57791e2d14247e8518a002a9b504c2bce69a25a26ab61948dcbec8789d358f46ce56010aa81d641f5a96fff0fa5cafd1b1d459c3972f90aa5dfaf6569f471c3113d65c187ae3a30bc5ce5c483a9a06fc1736990d4e03705d5a96a1b5103965ca7cb6a00c95bdf8e88c9dc1f2326c95af236f1f68146de2c7cd589a40e91a5b626b5061000b7c6d9acdccba01f8aa7cad17576315f031d9c3050a409c0354c3d90a170727aa69b8b70d6e30089b3152bbc1c4924b981cb06718afcd48e6111e94772545133a5e8ab0a3772d78635e169a3e91d7c8c0389523e7f15089714818326d708c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","groth16_vkey_hash":[106,41,6,172,110,196,97,200,202,205,91,53,87,21,127,89,49,123,213,114,229,123,200,37,57,117,170,245,197,172,180,136]}},"stdin":{"buffer":[[11,0,0,0,0,0,0,0]],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[1]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/is-prime_plonk_proof.json b/examples/wasm_example/data/is-prime_plonk_proof.json new file mode 100644 index 0000000..7b66c5e --- /dev/null +++ b/examples/wasm_example/data/is-prime_plonk_proof.json @@ -0,0 +1 @@ +{"proof":{"Plonk":{"public_inputs":["79974752685130133349989020271128338092086594955138314388631360057283056061","5408444369343130360314198614562428875014335023761526637751134529685417182618"],"encoded_proof":"0973da201577ae244b4f27a74e7303f20b779e2994fd15a20ecf35c7eb44824f039aea4f9eabcbbade4fbde0b2868994d80ff8bcb7c4303588594ee4b2ec844406f4e87b8e8fd35694b5c33b94c915ba5e66b590abf886168130763e2ee3f413152910a9b571f1195980344cac50a17ba3692f33edf6dbb61af4bfa7771ac3cd2fd22e672f4d0eb9921817a9d68cd5b312a58e1ee4bdfa9030010c7c86d9bf0c0ea56195721ae59442f72bbf9579a45a5f0a449713b66956fbb57ba44aa63e1007373a317932303728e8d0c1da55239420f9e9be45bf701dc568877ca46adddc2b2abc8e6ebb632dad0250edc2f3b8fcb7ee76650b903533f4f8e2c70a7302551cdc7852d8a8f23986b97463ca00dbaf15bbde95acaaabb1529be85d04f425470b2a05aedbbe2840bef213cf1b361bbc8ddc5af1afa0dd7b9d8f98856fdf32c30ed59b449f1f3e7fd379bdc527b1997f2c65df2ceb1fe716b1f9a689fceb814400682c94c78067a529593b30965bfbeccc095fd5b1eea72750098a3eaf7983692619aea64181292b9dce108d33374fa7b60e27328abad7407546dc20b095c08b22a957227bb13b726bb3ea2faff99fe5c78c0d3b130eadf7fe06cac70029d2d621747afa6679ca83dc6a17e9801ddc899232e4a6f931b816df144471e898df5f1f85cfd1d5f2569dcb3c78fff45244d276e54b6bce08cae1decc8ba81d615ecf12e9acb09dcb760c8a9d4dc3504a5f1e67f54eeb7465e074dd4942c80ce8aade04e30c01ee14cc0ceae2cc00f9d171489dfc0fb0da8fd4d187104c7322ba7e5d1fb1218bc264eac64a36e3a8244dc4806d845f11c055d7fb2f8d35877a366aa422fb7a8dac0c734383286433288803b43b694e2a3ede3cf74a08df523f094e3129521f97bf34d2e84a24d6683b9faee91895c448dfd0af250b70971b184f7af206299aa455c3ce64a181d0d86030fbd7ba2600c33e02ccd239a1401dbcc4ea572a275e0ff36074956319cb64e3483bad98193ae2ea95821c406ee9617790fe570d496b062be351566e4e723e4d0697c1559daa6b9f159bf53da66a2a508633e4103cd86778387d0623a3138dfe1596eb141de042e281c3f5aaee1154ff8345530e3202f68ac1b88836e32656411334f3e1668523ad3b810d8ead2335adb77e7805996ea733fee9c8359ac62e0c7194b7b3ec204c5b989b0d19c27255c72310ca","raw_proof":"0973da201577ae244b4f27a74e7303f20b779e2994fd15a20ecf35c7eb44824f039aea4f9eabcbbade4fbde0b2868994d80ff8bcb7c4303588594ee4b2ec844406f4e87b8e8fd35694b5c33b94c915ba5e66b590abf886168130763e2ee3f413152910a9b571f1195980344cac50a17ba3692f33edf6dbb61af4bfa7771ac3cd2fd22e672f4d0eb9921817a9d68cd5b312a58e1ee4bdfa9030010c7c86d9bf0c0ea56195721ae59442f72bbf9579a45a5f0a449713b66956fbb57ba44aa63e1004e30c01ee14cc0ceae2cc00f9d171489dfc0fb0da8fd4d187104c7322ba7e5d1fb1218bc264eac64a36e3a8244dc4806d845f11c055d7fb2f8d35877a366aa407373a317932303728e8d0c1da55239420f9e9be45bf701dc568877ca46adddc2b2abc8e6ebb632dad0250edc2f3b8fcb7ee76650b903533f4f8e2c70a7302551cdc7852d8a8f23986b97463ca00dbaf15bbde95acaaabb1529be85d04f425470b2a05aedbbe2840bef213cf1b361bbc8ddc5af1afa0dd7b9d8f98856fdf32c30ed59b449f1f3e7fd379bdc527b1997f2c65df2ceb1fe716b1f9a689fceb814400682c94c78067a529593b30965bfbeccc095fd5b1eea72750098a3eaf79836929521f97bf34d2e84a24d6683b9faee91895c448dfd0af250b70971b184f7af206299aa455c3ce64a181d0d86030fbd7ba2600c33e02ccd239a1401dbcc4ea57000000071e25d230403568dfc46145bb41153c4936bf7392dae70bdb98678571b4b739322619aea64181292b9dce108d33374fa7b60e27328abad7407546dc20b095c08b22a957227bb13b726bb3ea2faff99fe5c78c0d3b130eadf7fe06cac70029d2d621747afa6679ca83dc6a17e9801ddc899232e4a6f931b816df144471e898df5f1f85cfd1d5f2569dcb3c78fff45244d276e54b6bce08cae1decc8ba81d615ecf12e9acb09dcb760c8a9d4dc3504a5f1e67f54eeb7465e074dd4942c80ce8aade103cd86778387d0623a3138dfe1596eb141de042e281c3f5aaee1154ff8345532a275e0ff36074956319cb64e3483bad98193ae2ea95821c406ee9617790fe570d496b062be351566e4e723e4d0697c1559daa6b9f159bf53da66a2a508633e422fb7a8dac0c734383286433288803b43b694e2a3ede3cf74a08df523f094e31000000010e3202f68ac1b88836e32656411334f3e1668523ad3b810d8ead2335adb77e7805996ea733fee9c8359ac62e0c7194b7b3ec204c5b989b0d19c27255c72310ca","plonk_vkey_hash":[74,202,36,10,62,82,150,230,165,101,249,141,199,40,198,244,143,141,228,121,42,143,163,101,3,140,59,134,149,33,118,245]}},"stdin":{"buffer":[[11,0,0,0,0,0,0,0]],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[1]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/sha2_groth16_proof.json b/examples/wasm_example/data/sha2_groth16_proof.json new file mode 100644 index 0000000..00429dc --- /dev/null +++ b/examples/wasm_example/data/sha2_groth16_proof.json @@ -0,0 +1 @@ +{"proof":{"Groth16":{"public_inputs":["333753178417635990896842768210159010692127263164264366641697763838969891624","1669258166902426033910600439979403418188664065762541458854010994191676651605"],"encoded_proof":"1087f1c44ea1412f74b48a818b75ce4b3a65cda2a3d0d710e7ce6e5a123e5cb202e0ad963d547a1fdfb7fcd3a4f740169afba884f93dfb9d21ff96f3a32074bd1be19e4d98261cee2a35fbe56ed7438c24e0ea29edf1739255c3ca915e99412d1ab6d5804eedf84afbbb3a054f8088367aebe5736b4588b5794f7b610bfb075b0eb13e4dad8c685c2314889e51aa196986f4e51f491502363138407a16708d2b0afb50d6929360a3f107529555fe1205049cb74c61bdd9264c36a19afe5cf8b90fd13388ccfda2205936d6dd0ff8f55cdb520269d461ba59e4ee52096d47405312478d0678238f4b12d4f9eb7dac6485ef6762257e8271aa03208c83528b7d11","raw_proof":"1087f1c44ea1412f74b48a818b75ce4b3a65cda2a3d0d710e7ce6e5a123e5cb202e0ad963d547a1fdfb7fcd3a4f740169afba884f93dfb9d21ff96f3a32074bd1be19e4d98261cee2a35fbe56ed7438c24e0ea29edf1739255c3ca915e99412d1ab6d5804eedf84afbbb3a054f8088367aebe5736b4588b5794f7b610bfb075b0eb13e4dad8c685c2314889e51aa196986f4e51f491502363138407a16708d2b0afb50d6929360a3f107529555fe1205049cb74c61bdd9264c36a19afe5cf8b90fd13388ccfda2205936d6dd0ff8f55cdb520269d461ba59e4ee52096d47405312478d0678238f4b12d4f9eb7dac6485ef6762257e8271aa03208c83528b7d110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","groth16_vkey_hash":[106,41,6,172,110,196,97,200,202,205,91,53,87,21,127,89,49,123,213,114,229,123,200,37,57,117,170,245,197,172,180,136]}},"stdin":{"buffer":[],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/sha2_plonk_proof.json b/examples/wasm_example/data/sha2_plonk_proof.json new file mode 100644 index 0000000..2ec584e --- /dev/null +++ b/examples/wasm_example/data/sha2_plonk_proof.json @@ -0,0 +1 @@ +{"proof":{"Plonk":{"public_inputs":["333753178417635990896842768210159010692127263164264366641697763838969891624","1669258166902426033910600439979403418188664065762541458854010994191676651605"],"encoded_proof":"03e0788594ae336678eceec4c7022d212b2dc9c657aeb890a0d46d9ea0ec8f981d592deb46772e307e3558d564b6014d596b88e9508800be97f923649d6b7fc725a9ce62d1f2d6707fb86fd061a97e0bea5701700b0698c908dde5aaacfc765f254037f542af56ec1d950390bdec8a667b55bb8a3a84fd06d06981388144e1641d69522d53051fbf062c84cd55ef43e20920b4266f4ba8d756066f4ef782f4ea0247f307cb8db9b88774b00ecae951dcd2ba0b8cf20a43441672f3dce9ded02f29c325cef4bd233bf451425020607f0e0d3cc45c859d830fcbbac1ccfeab97dc1724d4d8b922af15f38730df412a7a07450f99df770b03a68783b2746fac9a6923708bd0e15b36cff126d64da055323b174a89f38fdca2364a4a95a8e496447009393e85707f082606aa8bf9508144ef105ed3eb1caad11e18deaa9c5fabc65906478f9c7bfcd222a2615f7905bc4bb06a6c22a5582026eb512daebe638e3d8d2af23a729e4489716ab2ecfe91835b3afb74ad8bcd5a807204631fbd77688093033e10db29f56f719cdac74483ab8977533a5bfd9756388623fa35834da416ff27011bfcf29b8f49f0d40679726e1d54e1157d1e3e2e2e2addd23bec5d265ee4298dc8a9c5d70cc5c491c1c6e638cbaf6b685f620bf28ccd6c3594ce8b450b0c2dd79d55571a4b03b87e6819cb1b8554e324d54a04773ba472261055d143a44d2b1193333f117edd4f5bb8e96bfe33787ca51fcceed50c79a434e3de83db9c18029301d127c3a6e550260d1676b19ec6b48ca050d2430683990d320476f4338c273b9a1b6c115f3b3efeefcab6dd87d2d83fb584d52093ad8171b2dc00757f051f147052b5be3386621b77cdff7116799eb814ea6e5ab24757f80935745b8c232921ebe06a54ec644d4ffb01ceabccf925b7c944ff819bb2075163702c85e8eb0eec17c3dc17689bf921566710b7af7cd147423dee3e1148a8e21ef27ddce894247390d5474c2a122c99422de0129a3541383c15b29b030991a9dc12a2db55080b4918a4b69d9e2a0a04b7042e83caba98f568400faa802302f5125421c0560e14b738df05a9154d2b6aba56ae8e25304c7a51f39a9d7d3975a5235aca22b4791983e47bdef2938d71eb188b3d8d92a38fdef513295084f9413c748636dd60952e47331e705e82f89e475a1c0208b52fd1aee18b3004357548f7a7038109902f","raw_proof":"03e0788594ae336678eceec4c7022d212b2dc9c657aeb890a0d46d9ea0ec8f981d592deb46772e307e3558d564b6014d596b88e9508800be97f923649d6b7fc725a9ce62d1f2d6707fb86fd061a97e0bea5701700b0698c908dde5aaacfc765f254037f542af56ec1d950390bdec8a667b55bb8a3a84fd06d06981388144e1641d69522d53051fbf062c84cd55ef43e20920b4266f4ba8d756066f4ef782f4ea0247f307cb8db9b88774b00ecae951dcd2ba0b8cf20a43441672f3dce9ded02f029301d127c3a6e550260d1676b19ec6b48ca050d2430683990d320476f4338c273b9a1b6c115f3b3efeefcab6dd87d2d83fb584d52093ad8171b2dc00757f0529c325cef4bd233bf451425020607f0e0d3cc45c859d830fcbbac1ccfeab97dc1724d4d8b922af15f38730df412a7a07450f99df770b03a68783b2746fac9a6923708bd0e15b36cff126d64da055323b174a89f38fdca2364a4a95a8e496447009393e85707f082606aa8bf9508144ef105ed3eb1caad11e18deaa9c5fabc65906478f9c7bfcd222a2615f7905bc4bb06a6c22a5582026eb512daebe638e3d8d2af23a729e4489716ab2ecfe91835b3afb74ad8bcd5a807204631fbd776880932921ebe06a54ec644d4ffb01ceabccf925b7c944ff819bb2075163702c85e8eb0eec17c3dc17689bf921566710b7af7cd147423dee3e1148a8e21ef27ddce8940000000719d1138c2b342dacce9cd36aea37aa9cfea26f1dfe83f74087170288c5546e8b033e10db29f56f719cdac74483ab8977533a5bfd9756388623fa35834da416ff27011bfcf29b8f49f0d40679726e1d54e1157d1e3e2e2e2addd23bec5d265ee4298dc8a9c5d70cc5c491c1c6e638cbaf6b685f620bf28ccd6c3594ce8b450b0c2dd79d55571a4b03b87e6819cb1b8554e324d54a04773ba472261055d143a44d2b1193333f117edd4f5bb8e96bfe33787ca51fcceed50c79a434e3de83db9c1814b738df05a9154d2b6aba56ae8e25304c7a51f39a9d7d3975a5235aca22b479247390d5474c2a122c99422de0129a3541383c15b29b030991a9dc12a2db55080b4918a4b69d9e2a0a04b7042e83caba98f568400faa802302f5125421c0560e1f147052b5be3386621b77cdff7116799eb814ea6e5ab24757f80935745b8c23000000011983e47bdef2938d71eb188b3d8d92a38fdef513295084f9413c748636dd60952e47331e705e82f89e475a1c0208b52fd1aee18b3004357548f7a7038109902f","plonk_vkey_hash":[74,202,36,10,62,82,150,230,165,101,249,141,199,40,198,244,143,141,228,121,42,143,163,101,3,140,59,134,149,33,118,245]}},"stdin":{"buffer":[],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/tendermint_groth16_proof.json b/examples/wasm_example/data/tendermint_groth16_proof.json new file mode 100644 index 0000000..f3b9400 --- /dev/null +++ b/examples/wasm_example/data/tendermint_groth16_proof.json @@ -0,0 +1 @@ +{"proof":{"Groth16":{"public_inputs":["155065531007377638360325702488831814382745954798402622842324467375504025268","1669258166902426033910600439979403418188664065762541458854010994191676651605"],"encoded_proof":"2680c9b0a2db001a5d3687e90904114a1203527db8b879c0fbe0f966f009c4b4285897ab07bc6f5a1144dca15b8c0013adc271cc8049e3d18e0e3b502eb825f00e9765761fcb507db1f2bde53db4045f3f0113b801dc0398f94975f1682323042de178511fda85b312e795e2821d01792ab0f276898611980fbb3085fc0a04a41e55cd66cf05b7455c19f41eb84110431c2da47ccdb44d6e097fa50ce342711b065d79ec6090ed92fc6a74d7158a77b1d44537ab7955f0fa8bd0f057687b08bd159bf4b3b64bbbd830cda07ef46ea3470304e47e8c469c06a9de3564d34624e02077e5f12b555ef5c7e03613ba6d318a4459a70d1a0e2444314ef8ceff11d48f","raw_proof":"2680c9b0a2db001a5d3687e90904114a1203527db8b879c0fbe0f966f009c4b4285897ab07bc6f5a1144dca15b8c0013adc271cc8049e3d18e0e3b502eb825f00e9765761fcb507db1f2bde53db4045f3f0113b801dc0398f94975f1682323042de178511fda85b312e795e2821d01792ab0f276898611980fbb3085fc0a04a41e55cd66cf05b7455c19f41eb84110431c2da47ccdb44d6e097fa50ce342711b065d79ec6090ed92fc6a74d7158a77b1d44537ab7955f0fa8bd0f057687b08bd159bf4b3b64bbbd830cda07ef46ea3470304e47e8c469c06a9de3564d34624e02077e5f12b555ef5c7e03613ba6d318a4459a70d1a0e2444314ef8ceff11d48f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","groth16_vkey_hash":[106,41,6,172,110,196,97,200,202,205,91,53,87,21,127,89,49,123,213,114,229,123,200,37,57,117,170,245,197,172,180,136]}},"stdin":{"buffer":[],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/data/tendermint_plonk_proof.json b/examples/wasm_example/data/tendermint_plonk_proof.json new file mode 100644 index 0000000..ef418f9 --- /dev/null +++ b/examples/wasm_example/data/tendermint_plonk_proof.json @@ -0,0 +1 @@ +{"proof":{"Plonk":{"public_inputs":["155065531007377638360325702488831814382745954798402622842324467375504025268","1669258166902426033910600439979403418188664065762541458854010994191676651605"],"encoded_proof":"013c49fea7dfae8b72eb325b43a83da91e5003c24e16bb98c1b1434bbfe6c709117a5aedf9a207bde11fc8666ceed4851b0d9d48ebd4323dff54291ef8bac00300603e69189ef1f0fd3e1c1c0e2ddddb280bdbd4e9fe2c326619566c3d86483001c56a7237b0d35739bd2425f5f93b17ec5a8b72aa5dc3b1cd93c5486aaf97d524b8558a8e37a7e1a1c97d1ddfb0476d0a345ac7ca9028bbeb5c2a4542093d6b2b65e259d28b59f4e1b73e01ac65945ce75a7b81c34d833a7d9b847bed2b58e00ba5f9c05b24ef3d4ef3da6232ffc70310bccfee6d2eb05e6ad52cefa74abb1006bf67087510b73806b31da3e469a558100ba8fcee90865686d8b024a68bc2a412406b068db778661bb306cb822774dfd7d94f0beeeb67943dc7ca0c41a668ee22b2a83e5c422e0ef37f06ffacd61a7eb82b2d0388eb7454a7d69d3a65b7de401ddb4fb2b3ef4fb95db1bf46b24fe126a8e0fa510dedde52e974466bfbab28970d6668f6c5d1cb3f4c1d1346b86831b6997893c26b332dd3af0d0027d33f1c881d9c5d684b04bb05d30beb728034bd7cba96cca999f3e124711537db1bf987360c05688e5417dafc3f33253dcc2daf89853e741954cc210bf6db1a9c400cbddf0268f613aacc34f6cfadb45d879de3247a30fb746b0b9a709b013daa4001a89b145be4969e2df8b2a76ff9c5893d9e66bd96af61165bdcb968b8fb653c417f080359232c930b30271d419255b3f8ba1f74cbb56833523c7dc89aa541926cae6903c6e7f9e3ac7369bf05973b572c33cab37ab91a4cea0e421fef22b1abe9bde1298981bdbb84f03105d81d4da3b685e842c594222690f6bc4f6ac62e966097e00ce9a1df62a243238829360b0c566231d89aa006d091dce5e1938276ebf91957128ff16dbbcad198a38e2b3bab85420aef2c7440eab9077bfc5435f4cdf9a16128f0eb51b433e5d6875f8717ca5c4cea4e45fa2613f79c1db65d85c7b1a7819d1d130e7e7f6ea98ea550969574f1d385278145a75bc5466bed7de2b3f65fc4a50e6ed21c40c87fdc1acafd00edd7216e2f1d262a42e7390526f7de1b475087a5053be958085183e3c3e083c8366543b220d4b54f76720f6a35cf701f2a77b8950b29b3248f5319e1f7e6d843cf14504bc0d3ec77b48cd6c6778f754497b9b4f32bf1b9a98799fc973ae93d61dcca8b688a9fe1893680812e70a158ef6471216b","raw_proof":"013c49fea7dfae8b72eb325b43a83da91e5003c24e16bb98c1b1434bbfe6c709117a5aedf9a207bde11fc8666ceed4851b0d9d48ebd4323dff54291ef8bac00300603e69189ef1f0fd3e1c1c0e2ddddb280bdbd4e9fe2c326619566c3d86483001c56a7237b0d35739bd2425f5f93b17ec5a8b72aa5dc3b1cd93c5486aaf97d524b8558a8e37a7e1a1c97d1ddfb0476d0a345ac7ca9028bbeb5c2a4542093d6b2b65e259d28b59f4e1b73e01ac65945ce75a7b81c34d833a7d9b847bed2b58e003c6e7f9e3ac7369bf05973b572c33cab37ab91a4cea0e421fef22b1abe9bde1298981bdbb84f03105d81d4da3b685e842c594222690f6bc4f6ac62e966097e00ba5f9c05b24ef3d4ef3da6232ffc70310bccfee6d2eb05e6ad52cefa74abb1006bf67087510b73806b31da3e469a558100ba8fcee90865686d8b024a68bc2a412406b068db778661bb306cb822774dfd7d94f0beeeb67943dc7ca0c41a668ee22b2a83e5c422e0ef37f06ffacd61a7eb82b2d0388eb7454a7d69d3a65b7de401ddb4fb2b3ef4fb95db1bf46b24fe126a8e0fa510dedde52e974466bfbab28970d6668f6c5d1cb3f4c1d1346b86831b6997893c26b332dd3af0d0027d33f1c88128ff16dbbcad198a38e2b3bab85420aef2c7440eab9077bfc5435f4cdf9a16128f0eb51b433e5d6875f8717ca5c4cea4e45fa2613f79c1db65d85c7b1a7819d00000007073da847fb81107a860dcbdf1dad269503e406bf30464c2461830dc7ee65189d1d9c5d684b04bb05d30beb728034bd7cba96cca999f3e124711537db1bf987360c05688e5417dafc3f33253dcc2daf89853e741954cc210bf6db1a9c400cbddf0268f613aacc34f6cfadb45d879de3247a30fb746b0b9a709b013daa4001a89b145be4969e2df8b2a76ff9c5893d9e66bd96af61165bdcb968b8fb653c417f080359232c930b30271d419255b3f8ba1f74cbb56833523c7dc89aa541926cae69053be958085183e3c3e083c8366543b220d4b54f76720f6a35cf701f2a77b8951d130e7e7f6ea98ea550969574f1d385278145a75bc5466bed7de2b3f65fc4a50e6ed21c40c87fdc1acafd00edd7216e2f1d262a42e7390526f7de1b475087a50ce9a1df62a243238829360b0c566231d89aa006d091dce5e1938276ebf91957000000010b29b3248f5319e1f7e6d843cf14504bc0d3ec77b48cd6c6778f754497b9b4f32bf1b9a98799fc973ae93d61dcca8b688a9fe1893680812e70a158ef6471216b","plonk_vkey_hash":[74,202,36,10,62,82,150,230,165,101,249,141,199,40,198,244,143,141,228,121,42,143,163,101,3,140,59,134,149,33,118,245]}},"stdin":{"buffer":[],"ptr":0,"proofs":[]},"public_values":{"buffer":{"data":[]}},"sp1_version":"v2.0.0"} \ No newline at end of file diff --git a/examples/wasm_example/main.js b/examples/wasm_example/main.js new file mode 100644 index 0000000..611936d --- /dev/null +++ b/examples/wasm_example/main.js @@ -0,0 +1,62 @@ +import * as wasm from "../../verifier/pkg/snark_bn254_verifier.js" +import fs from 'node:fs' +import path from 'node:path' +import assert from 'node:assert' +import { homedir } from "node:os"; + + +// Read the verification keys for Groth16 and Plonk from the file system +const GROTH16_VK_BYTES = new Uint8Array(fs.readFileSync( + path.join(homedir(), '.sp1/circuits/v2.0.0/groth16_vk.bin') +)); +const PLONK_VK_BYTES = new Uint8Array(fs.readFileSync( + path.join(homedir(), '.sp1/circuits/v2.0.0/plonk_vk.bin') +)); + +// Pad a Uint8Array to 32 bytes +const pad32Bytes = (x) => { + const padding = new Uint8Array(32 - x.length).fill(0); + return new Uint8Array([...padding, ...x]) +} + +// Convert a hexadecimal string to a Uint8Array +export const fromHexString = (hexString) => + Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); + +// Convert a big number to a padded Uint8Array +export function fromBigNumber(number) { + var array = [], bigint = BigInt(number) + // Convert the number to bytes + for (let i = 0; i < Math.ceil(Math.floor(Math.log2(new Number(number)) + 1) / 8); i++) + array.unshift(new Number((bigint >> BigInt(8 * i)) & 255n)) + // Pad the resulting array to 32 bytes + return pad32Bytes(new Uint8Array(array)); +} + + +const files = fs.readdirSync("./data"); + +// Iterate through each file in the data directory +for (const file of files) { + try { + // Read and parse the JSON content of the file + const fileContent = fs.readFileSync(path.join("./data", file), 'utf8'); + const { proof } = JSON.parse(fileContent); + + // Determine the ZKP type (Groth16 or Plonk) based on the filename + const zkpType = file.toLowerCase().includes('groth16') ? 'Groth16' : 'Plonk'; + const { raw_proof, public_inputs } = proof[zkpType]; + + // Select the appropriate verification function and verification key based on ZKP type + const verifyFunction = zkpType === 'Groth16' ? wasm.wasm_verify_groth16 : wasm.wasm_verify_plonk; + const vkBytes = zkpType === 'Groth16' ? GROTH16_VK_BYTES : PLONK_VK_BYTES; + + // The array is a flattened array of 32-byte segments + const formattedPublicInputs = public_inputs.map(input => fromBigNumber(BigInt(input))).reduce((acc, val) => [...acc, ...val], []); + + assert(verifyFunction(fromHexString(raw_proof), vkBytes, formattedPublicInputs)); + console.log(`Proof in ${file} is valid.`); + } catch (error) { + console.error(`Error processing ${file}: ${error.message}`); + } +} \ No newline at end of file diff --git a/examples/wasm_example/package.json b/examples/wasm_example/package.json new file mode 100644 index 0000000..3cd4ded --- /dev/null +++ b/examples/wasm_example/package.json @@ -0,0 +1,13 @@ +{ + "name": "wasm_example", + "version": "1.0.0", + "description": "WASM Bindings for Plonk/Groth16 Verification on the BN254 Curve", + "main": "main.js", + "scripts": { + "test": "node main.js" + }, + "keywords": [], + "author": "Bhargav Annem", + "license": "ISC", + "type": "module" +} \ No newline at end of file diff --git a/examples/wasm_example/pnpm-lock.yaml b/examples/wasm_example/pnpm-lock.yaml new file mode 100644 index 0000000..9b60ae1 --- /dev/null +++ b/examples/wasm_example/pnpm-lock.yaml @@ -0,0 +1,9 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} diff --git a/verifier/Cargo.toml b/verifier/Cargo.toml index 3c6bee0..194c492 100644 --- a/verifier/Cargo.toml +++ b/verifier/Cargo.toml @@ -19,3 +19,10 @@ num-traits = "0.2.19" rand = "0.8.5" sha2 = "0.10.8" thiserror = "1.0.63" +wasm-bindgen = "0.2.93" + +[lib] +crate-type = ["cdylib", "rlib"] + +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = ["js"] } diff --git a/verifier/src/groth16/converter.rs b/verifier/src/groth16/converter.rs index c71e622..40bcce7 100644 --- a/verifier/src/groth16/converter.rs +++ b/verifier/src/groth16/converter.rs @@ -70,12 +70,12 @@ pub(crate) fn load_groth16_verifying_key_from_bytes( Ok(Groth16VerifyingKey { g1: Groth16G1 { alpha: g1_alpha, - beta: -g1_beta, + beta: g1_beta, delta: g1_delta, k, }, g2: Groth16G2 { - beta: -g2_beta, + beta: g2_beta, gamma: g2_gamma, delta: g2_delta, }, diff --git a/verifier/src/groth16/verify.rs b/verifier/src/groth16/verify.rs index 057389f..dbeb765 100644 --- a/verifier/src/groth16/verify.rs +++ b/verifier/src/groth16/verify.rs @@ -1,4 +1,4 @@ -use bn::{pairing, pairing_batch, AffineG1, AffineG2, Fr, Gt, G1, G2}; +use bn::{pairing_batch, AffineG1, AffineG2, Fr, Gt, G1, G2}; use super::error::Groth16Error; @@ -66,12 +66,12 @@ pub fn verify_groth16( proof: &Groth16Proof, public_inputs: &[Fr], ) -> Result { - let alpha_g1_beta_g2 = pairing(vk.g1.alpha.into(), vk.g2.beta.into()); let prepared_inputs = prepare_inputs(vk.clone(), public_inputs)?; Ok(pairing_batch(&[ (proof.ar.into(), proof.bs.into()), (prepared_inputs, vk.g2.gamma.into()), (proof.krs.into(), -Into::::into(vk.g2.delta)), - ]) == alpha_g1_beta_g2) + (vk.g1.alpha.into(), vk.g2.beta.into()), + ]) == Gt::one()) } diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index 8b03d12..919f833 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -4,7 +4,7 @@ //! This crate provides verifiers for Groth16 and Plonk zero-knowledge proofs. -use bn::Fr; +pub use bn::Fr; use groth16::{ error::Groth16Error, load_groth16_proof_from_bytes, load_groth16_verifying_key_from_bytes, verify_groth16, @@ -21,6 +21,8 @@ mod groth16; mod hash_to_field; mod plonk; mod transcript; +#[cfg(target_arch = "wasm32")] +pub mod wasm; /// A verifier for Groth16 zero-knowledge proofs. #[derive(Debug)] diff --git a/verifier/src/wasm.rs b/verifier/src/wasm.rs new file mode 100644 index 0000000..f054e4e --- /dev/null +++ b/verifier/src/wasm.rs @@ -0,0 +1,52 @@ +//! WASM bindings for the verifier. + +use crate::{Groth16Verifier, PlonkVerifier}; +use bn::Fr; +use wasm_bindgen::prelude::*; + +fn load_public_inputs(public_inputs: &[u8]) -> Result, JsValue> { + public_inputs + .chunks(32) + .map(|chunk| Fr::from_slice(chunk).map_err(|e| JsValue::from_str(&e.to_string()))) + .collect() +} + +/// Verifies a Groth16 proof using WebAssembly. +/// +/// # Arguments +/// +/// * `proof` - The proof bytes. +/// * `vk` - The verification key bytes. +/// * `public_inputs` - The public inputs bytes. This must be a concatenated array big-endian 32-byte segments representing scalar field elements +/// +/// # Returns +/// +/// A `Result` containing a boolean indicating whether the proof is valid, +/// or a `Groth16Error` if verification fails. +#[wasm_bindgen] +pub fn wasm_verify_groth16(proof: &[u8], vk: &[u8], public_inputs: &[u8]) -> Result { + let public_inputs = load_public_inputs(public_inputs)?; + + Groth16Verifier::verify(&proof, &vk, &public_inputs) + .map_err(|e| JsValue::from_str(&e.to_string())) +} + +/// Verifies a Plonk proof using WebAssembly. +/// +/// # Arguments +/// +/// * `proof` - The proof bytes. +/// * `vk` - The verification key bytes. +/// * `public_inputs` - The public inputs bytes. This must be a concatenated array of big-endian 32-byte segments representing scalar field elements +/// +/// # Returns +/// +/// A `Result` containing a boolean indicating whether the proof is valid, +/// or a `JsValue` containing an error message if verification fails. +#[wasm_bindgen] +pub fn wasm_verify_plonk(proof: &[u8], vk: &[u8], public_inputs: &[u8]) -> Result { + let public_inputs = load_public_inputs(public_inputs)?; + + PlonkVerifier::verify(&proof, &vk, &public_inputs) + .map_err(|e| JsValue::from_str(&e.to_string())) +}