From 75eee20ba78dad2f9fb786543b1bb5372efd404b Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 19 Apr 2023 13:05:22 -0700 Subject: [PATCH] Multithreading proof generation from wasm --- .cargo/config | 3 + Cargo.lock | 261 +++++++-------- Cargo.toml | 13 +- rust/Cargo.toml | 22 +- rust/src/api/asynchronous.rs | 127 ++++++++ sdk/jestconfig.json | 7 + wasm/Cargo.toml | 67 +++- wasm/rust-toolchain | 1 + wasm/src/account/view_key.rs | 16 +- wasm/src/lib.rs | 6 + wasm/src/program/decrypt.rs | 302 ++++++++++++++++++ wasm/src/program/intermediate_transaction.rs | 28 ++ wasm/src/program/mod.rs | 33 ++ wasm/src/program/program.rs | 81 +++++ wasm/src/program/proving_key.rs | 91 ++++++ wasm/src/program/transaction.rs | 290 +++++++++++++++++ wasm/src/program/verifying_key.rs | 72 +++++ wasm/src/record/record_plaintext.rs | 11 - wasm/src/types.rs | 43 ++- website/.babelrc | 6 + website/.gitignore | 26 ++ website/package.json | 8 +- website/pkg/index.js | 0 website/public/logo192.png | Bin 0 -> 12574 bytes website/src/App.js | 11 +- website/src/db/index.js | 124 +++++++ website/src/tabs/transaction/SendCredits.js | 214 +++++++++++++ website/src/tabs/transaction/getChainState.js | 27 ++ website/src/workers/worker.js | 105 ++++++ website/webpack.config.js | 40 ++- website/yarn.lock | 42 +++ 31 files changed, 1884 insertions(+), 193 deletions(-) create mode 100644 rust/src/api/asynchronous.rs create mode 100644 sdk/jestconfig.json create mode 100644 wasm/rust-toolchain create mode 100644 wasm/src/program/decrypt.rs create mode 100644 wasm/src/program/intermediate_transaction.rs create mode 100644 wasm/src/program/mod.rs create mode 100644 wasm/src/program/program.rs create mode 100644 wasm/src/program/proving_key.rs create mode 100644 wasm/src/program/transaction.rs create mode 100644 wasm/src/program/verifying_key.rs create mode 100644 website/.babelrc create mode 100644 website/.gitignore create mode 100644 website/pkg/index.js create mode 100644 website/public/logo192.png create mode 100644 website/src/db/index.js create mode 100644 website/src/tabs/transaction/SendCredits.js create mode 100644 website/src/tabs/transaction/getChainState.js create mode 100644 website/src/workers/worker.js diff --git a/.cargo/config b/.cargo/config index 7c6d59471..f2d74754d 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,2 +1,5 @@ [target.'cfg(not(target_arch = "wasm32"))'] rustflags = ["-C", "target-cpu=native"] + +[target.wasm32-unknown-unknown] +rustflags = ["-C", "link-arg=--max-memory=4294967296"] \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index dc4a1d54b..85994e4c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,9 @@ dependencies = [ "serde_json", "snarkvm", "snarkvm-console", + "snarkvm-synthesizer", + "snarkvm-utilities", + "snarkvm-wasm", "ureq", ] @@ -163,11 +166,20 @@ dependencies = [ "console_error_panic_hook", "getrandom", "hex", + "js-sys", "rand", + "rand_chacha", + "rayon", + "serde", + "serde-wasm-bindgen", "serde_json", + "snarkvm-console", + "snarkvm-synthesizer", "snarkvm-wasm", "wasm-bindgen", + "wasm-bindgen-rayon", "wasm-bindgen-test", + "web-sys", ] [[package]] @@ -255,9 +267,9 @@ dependencies = [ [[package]] name = "blake2s_simd" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" +checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" dependencies = [ "arrayref", "arrayvec", @@ -393,9 +405,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" @@ -454,9 +466,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", @@ -639,9 +651,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -1131,9 +1143,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -1171,14 +1183,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.42.0", ] [[package]] @@ -1878,18 +1890,29 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2 1.0.54", "quote 1.0.26", @@ -1898,9 +1921,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "indexmap", "itoa", @@ -1989,14 +2012,13 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "snarkvm" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c5ce5ec3f31d3884ebbe5742ebe4e202e6fde0ba354e018194e0048b97ec2a0" +version = "0.10.2" dependencies = [ "anyhow", "clap", "colored", "indexmap", + "num-format", "once_cell", "parking_lot", "rand", @@ -2015,9 +2037,7 @@ dependencies = [ [[package]] name = "snarkvm-algorithms" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07aa0f93ba4fec19ad612bc5c545a581e7b9711f4fdb7c60308c65667195a9" +version = "0.10.2" dependencies = [ "aleo-std", "anyhow", @@ -2038,13 +2058,12 @@ dependencies = [ "snarkvm-r1cs", "snarkvm-utilities", "thiserror", + "web-sys", ] [[package]] name = "snarkvm-circuit" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d081367e4a256b5e41fd5ef7385b9d5c810cd11d4b443c286ebc58273ecf704f" +version = "0.10.2" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -2057,9 +2076,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-account" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2983871a63a9b4d866dd820f2eb879b52748b0021fdbcd5be0428d5af86672d1" +version = "0.10.2" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-network", @@ -2069,9 +2086,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-algorithms" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa93fdb148cf64178c6de0d84aa3a1c469d1c4d38cc1990e60b7d3ab7bab5e7" +version = "0.10.2" dependencies = [ "snarkvm-circuit-types", "snarkvm-console-algorithms", @@ -2080,9 +2095,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-collections" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2974cdad52a9520c804912d0f7999c16eac9490ceb4deb718543bdae74d24575" +version = "0.10.2" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-types", @@ -2091,9 +2104,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ae9958c57a53a68326f801e188aa9e2c242f8da639ac62a9d0110ace3cb211" +version = "0.10.2" dependencies = [ "indexmap", "itertools", @@ -2110,15 +2121,11 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment-witness" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05208a9b68281e5647e494953e1f28f46daabef7a8471db4584bcc2eef848933" +version = "0.10.2" [[package]] name = "snarkvm-circuit-network" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca98609055dadccab650a52924046cbe5023788cde13b4d33718bfc8fb97a7c" +version = "0.10.2" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -2128,9 +2135,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-program" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e333aa328cb25229a55c63eb643af9cabb6105404d744520db759970c4d176" +version = "0.10.2" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-collections", @@ -2142,9 +2147,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03162c34cb55ed61fd0ebbd567ac5c3a679d93436f376ae1a6fd4c009155d440" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -2158,9 +2161,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-address" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e622a535a68fd695f987efd5a01b14c119b964bf7ca20ac4fb1a2b180959c9" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2172,9 +2173,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-boolean" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bf5ad2d81dd9d9248274c0c9c289ada8055198a72f99c527d2d16ba32300cb" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-console-types-boolean", @@ -2182,9 +2181,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-field" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce314b46b2785be23853069e6098129d4104846750cf0c9c1d9f473a3cfff78" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2193,9 +2190,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-group" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbbd93fc54085d92f08c2c4c93487f123ed50a063978fe8279a5925e4411f0d" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2206,9 +2201,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-integers" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22af00a59fc943b1537519ad084eee2328795f1acb18d4257e4c81edca0c1d42" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2218,9 +2211,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-scalar" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56d3e76252d21c82c39e82c698a32761f7edd5b67e790977c5de5ec0ddb926c" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2230,9 +2221,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-string" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace13b3fb6299f461ccc7129d4733eec712e137aa77089f52b2c0b4890ceb09d" +version = "0.10.2" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2243,9 +2232,7 @@ dependencies = [ [[package]] name = "snarkvm-console" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d698128fe3e9ae4bfb1f71603a8e53bcc327a6dc6de5e2fdfc7c14261d0249" +version = "0.10.2" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -2257,9 +2244,7 @@ dependencies = [ [[package]] name = "snarkvm-console-account" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634c8b94dbb3bd100f84b90301b5daefce190cc30cfed5f564f4b00e488c0a09" +version = "0.10.2" dependencies = [ "bs58", "snarkvm-console-network", @@ -2268,9 +2253,7 @@ dependencies = [ [[package]] name = "snarkvm-console-algorithms" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5188f23cdc492d4a303f39bcb43898c9932bd26d6fa64ddee31fdd069f014284" +version = "0.10.2" dependencies = [ "blake2s_simd", "smallvec", @@ -2281,9 +2264,7 @@ dependencies = [ [[package]] name = "snarkvm-console-collections" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4d074e20484b10a82755429aca879d6887a399b358af3c64fd8fe514bb9062" +version = "0.10.2" dependencies = [ "aleo-std", "rayon", @@ -2293,9 +2274,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be3213fa6407162a4280048f6fc5cd3132fe019b384724ef8a0d93c8f4d8e8d9" +version = "0.10.2" dependencies = [ "anyhow", "indexmap", @@ -2317,9 +2296,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network-environment" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fce81ef18f9f8464c576561203b01b2e514613d005bfb5d8eac2dd95f84e6f3" +version = "0.10.2" dependencies = [ "anyhow", "bech32", @@ -2335,9 +2312,7 @@ dependencies = [ [[package]] name = "snarkvm-console-program" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740b0c22ceb96df55c9cc7e85d1431f3da2da6f8ecfa7277b3b2da27d4583703" +version = "0.10.2" dependencies = [ "enum_index", "enum_index_derive", @@ -2355,9 +2330,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f9c717deedb471c51eb29b96a898ba9c1b4cc29ef9daacc6549d9ed0c7ef52" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-address", @@ -2371,9 +2344,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-address" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3a481bcff24c35b14940cb7ca97944f3426bff31e0dd267e95e6af5c63ce75" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2383,18 +2354,14 @@ dependencies = [ [[package]] name = "snarkvm-console-types-boolean" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31f22f5cb9f6b2a5a47b7df4e77c8b63f873b52356666a75568908a67346585" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", ] [[package]] name = "snarkvm-console-types-field" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4d98e0e7afb3deadf3221b3700c0385533b69fc32b2a1ccf7622d6858b1def" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2402,9 +2369,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-group" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266f6ce35d14946d98e27a5eba6de0bf565626396d161b9e318c46bd4446556" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2414,9 +2379,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-integers" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f95e929a67bb5e0be38fc435acd293f68e539d583f927d4c59f8885a7c0133f" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2425,9 +2388,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-scalar" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de584696534d3495235aae9dc08bcd416ad526f057f4fb16ac73f7f6a2143dd" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2436,9 +2397,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-string" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf39608562f0d9f546b3e21957e9e6bdf1652da33ba070a6a89ba800213029bf" +version = "0.10.2" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -2448,9 +2407,7 @@ dependencies = [ [[package]] name = "snarkvm-curves" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15207cc7eab86e4b1b7aed4b20dbaf26f8cbd9918b19dc84ec97652a8aa70d48" +version = "0.10.2" dependencies = [ "rand", "rayon", @@ -2463,9 +2420,7 @@ dependencies = [ [[package]] name = "snarkvm-fields" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d8160d1cd923d81fd9f7c4463a07707ccd4bcd429f9e12459098422cf0812d" +version = "0.10.2" dependencies = [ "aleo-std", "anyhow", @@ -2481,9 +2436,7 @@ dependencies = [ [[package]] name = "snarkvm-parameters" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c030fc55bfce30b7e39ac88f5c5c0214dad03c4de9f079f4a972bc469e1f55" +version = "0.10.2" dependencies = [ "aleo-std", "anyhow", @@ -2509,9 +2462,7 @@ dependencies = [ [[package]] name = "snarkvm-r1cs" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf45f2a4a7aedc3d6bff6b408db79cdbc9dbfdef9b43d2454ee1bb2cd9a7612" +version = "0.10.2" dependencies = [ "anyhow", "cfg-if", @@ -2526,12 +2477,11 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3314a3e494522e1e0f64d9d5cd05ae1af23c5b4e2d88611780e0783f1b71c38" +version = "0.10.2" dependencies = [ "aleo-std", "anyhow", + "bincode", "blake2", "colored", "indexmap", @@ -2555,9 +2505,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34038d6351815ade16f1d7fe6d34fc723b990a9e200ee7dda5c8e3785f914f8" +version = "0.10.2" dependencies = [ "aleo-std", "anyhow", @@ -2575,9 +2523,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities-derives" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "541b2488455c3194799b66349714f7891c47d7a7d16413c3b46c0ab280102d4f" +version = "0.10.2" dependencies = [ "proc-macro2 1.0.54", "quote 1.0.26", @@ -2586,15 +2532,16 @@ dependencies = [ [[package]] name = "snarkvm-wasm" -version = "0.9.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5da8cad05cc7173de0b32f6acdeacbdd34ff5b1db05dc5b4096583d37c6c3" +version = "0.10.2" dependencies = [ "getrandom", "rand", "serde", + "snarkvm-circuit", "snarkvm-console", + "snarkvm-curves", "snarkvm-fields", + "snarkvm-synthesizer", "snarkvm-utilities", "wasm-bindgen", ] @@ -2615,6 +2562,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spmc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5" + [[package]] name = "strsim" version = "0.10.0" @@ -2777,9 +2730,9 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" @@ -2813,9 +2766,9 @@ dependencies = [ [[package]] name = "tokio-native-tls" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", "tokio", @@ -2846,9 +2799,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -3199,6 +3152,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df87c67450805c305d3ae44a3ac537b0253d029153c25afc3ecd2edc36ccafb1" +dependencies = [ + "js-sys", + "rayon", + "spmc", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-shared" version = "0.2.84" diff --git a/Cargo.toml b/Cargo.toml index d5f8fbb6e..e19331e5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,14 +26,21 @@ path = "rust" default-features = false [workspace.dependencies.snarkvm] -version = "0.9.16" +version = "0.10.2" +path="../snarkVM" [workspace.dependencies.snarkvm-console] -version = "0.9.16" +version = "0.10.2" +path="../snarkVM/console" [workspace.dependencies.snarkvm-wasm] -version = "0.9.16" +version = "0.10.2" default-features = false +path="../snarkVM/wasm" + +[workspace.dependencies.snarkvm-synthesizer] +path="../snarkVM/synthesizer" +version = "0.10.2" [lib] path = "cli/lib.rs" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index bbfec06b9..eacb07cbb 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -49,11 +49,29 @@ version = "2.6.2" version = "1.0.91" [dependencies.snarkvm] +version = "0.10.2" +path="../../snarkVM" +optional=true + +[dependencies.snarkvm-wasm] +version = "0.10.2" +path="../../snarkVM/wasm" + +[dependencies.snarkvm-utilities] +version = "0.10.2" +path="../../snarkVM/utilities" + +[dependencies.snarkvm-synthesizer] +version = "0.10.2" +path = "../../snarkVM/synthesizer" +default-features = false +features = [ "wasm" ] optional = true -workspace = true [dependencies.snarkvm-console] -workspace = true +path = "../../snarkVM/console" +default-features = false +version = "0.10.2" [dev-dependencies.bencher] version = "0.1.5" diff --git a/rust/src/api/asynchronous.rs b/rust/src/api/asynchronous.rs new file mode 100644 index 000000000..719fe35c8 --- /dev/null +++ b/rust/src/api/asynchronous.rs @@ -0,0 +1,127 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::AleoAPIClient; + +use anyhow::{anyhow, bail, Result}; +use snarkvm_console::{ + program::{Network, ProgramID}, + types::Field, +}; +use snarkvm_synthesizer::{Block, Program, Transaction}; +use std::convert::TryInto; + +impl AleoAPIClient { + pub async fn latest_height(&self) -> Result { + let url = format!("{}/{}/latest/height", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(height) => Ok(height), + Err(error) => bail!("Failed to parse the latest block height: {error}"), + } + } + + pub async fn latest_hash(&self) -> Result { + let url = format!("{}/{}/latest/hash", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(hash) => Ok(hash), + Err(error) => bail!("Failed to parse the latest block hash: {error}"), + } + } + + pub async fn latest_block(&self) -> Result> { + let url = format!("{}/{}/latest/block", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(block) => Ok(block), + Err(error) => bail!("Failed to parse the latest block: {error}"), + } + } + + pub async fn get_block(&self, height: u32) -> Result> { + let url = format!("{}/{}/block/{height}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(block) => Ok(block), + Err(error) => bail!("Failed to parse block {height}: {error}"), + } + } + + pub async fn get_blocks(&self, start_height: u32, end_height: u32) -> Result>> { + if start_height >= end_height { + bail!("Start height must be less than end height"); + } else if end_height - start_height > 50 { + bail!("Cannot request more than 50 blocks at a time"); + } + + let url = format!("{}/{}/blocks?start={start_height}&end={end_height}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(blocks) => Ok(blocks), + Err(error) => { + bail!("Failed to parse blocks {start_height} (inclusive) to {end_height} (exclusive): {error}") + } + } + } + + pub async fn get_transaction(&self, transaction_id: N::TransactionID) -> Result> { + let url = format!("{}/{}/transaction/{transaction_id}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(transaction) => Ok(transaction), + Err(error) => bail!("Failed to parse transaction '{transaction_id}': {error}"), + } + } + + pub async fn get_memory_pool_transactions(&self) -> Result>> { + let url = format!("{}/{}/memoryPool/transactions", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(transactions) => Ok(transactions), + Err(error) => bail!("Failed to parse memory pool transactions: {error}"), + } + } + + pub async fn get_program(&self, program_id: impl TryInto>) -> Result> { + // Prepare the program ID. + let program_id = program_id.try_into().map_err(|_| anyhow!("Invalid program ID"))?; + // Perform the request. + let url = format!("{}/{}/program/{program_id}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(program) => Ok(program), + Err(error) => bail!("Failed to parse program {program_id}: {error}"), + } + } + + pub async fn find_block_hash(&self, transaction_id: N::TransactionID) -> Result { + let url = format!("{}/{}/find/blockHash/{transaction_id}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(hash) => Ok(hash), + Err(error) => bail!("Failed to parse block hash: {error}"), + } + } + + /// Returns the transition ID that contains the given `input ID` or `output ID`. + pub async fn find_transition_id(&self, input_or_output_id: Field) -> Result { + let url = format!("{}/{}/find/transitionID/{input_or_output_id}", self.base_url, self.chain); + match self.client.get(url).send().await?.json().await { + Ok(transition_id) => Ok(transition_id), + Err(error) => bail!("Failed to parse transition ID: {error}"), + } + } + + pub async fn transaction_broadcast(&self, transaction: Transaction) -> Result> { + let url = format!("{}/{}/transaction/broadcast", self.base_url, self.chain); + match self.client.post(url).body(serde_json::to_string(&transaction)?).send().await?.json().await { + Ok(block) => Ok(block), + Err(error) => bail!("Failed to parse memory pool transactions: {error}"), + } + } +} diff --git a/sdk/jestconfig.json b/sdk/jestconfig.json new file mode 100644 index 000000000..20c25c0f7 --- /dev/null +++ b/sdk/jestconfig.json @@ -0,0 +1,7 @@ +{ + "transform": { + "^.+\\.(t|j)sx?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"] +} diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 2f1daecb8..a82dff649 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -20,9 +20,22 @@ edition = "2021" [lib] crate-type = [ "cdylib", "rlib" ] +[features] +default = [ + "snarkvm-synthesizer/serial", + "snarkvm-console/serial", + "snarkvm-wasm/serial", +] +frontend-parallel = [ + "wasm-bindgen-rayon", + "snarkvm-synthesizer/web", +] + [dependencies.aleo-rust] +version = "0.3.4" +path = "../rust" features = [ "wasm" ] -workspace = true +default-features = false [dependencies.anyhow] version = "1.0" @@ -39,17 +52,65 @@ version = "0.8" [dependencies.serde_json] version = "1.0" +features = [ "preserve_order" ] + +[dependencies.snarkvm-synthesizer] +path="../../snarkVM/synthesizer" +version = "0.10.2" +default-features = false +features = [ "wasm" ] + +[dependencies.snarkvm-console] +path="../../snarkVM/console" +version = "0.10.2" +default-features = false +features = [ ] [dependencies.snarkvm-wasm] -workspace = true -features = [ "console", "fields", "utilities" ] +path="../../snarkVM/wasm" +version = "0.10.2" [dependencies.wasm-bindgen] version = "0.2" features = [ "serde-serialize" ] +[dependencies.js-sys] +version = "0.3" + +[dependencies.web-sys] +version = "0.3" +features = ["console"] + +[dependencies.serde] +version = "1.0" +features = ["derive"] + +[dependencies.serde-wasm-bindgen] +version = "0.4" + [dependencies.console_error_panic_hook] version = "0.1.7" +[dependencies.rand_chacha] +version = "0.3.1" + +[dependencies.wasm-bindgen-rayon] +version = "1.0" +optional = true + +[dependencies.rayon] +version = "1.5" +optional = true + [dev-dependencies.wasm-bindgen-test] version = "0.3.33" + +[profile.release] +opt-level = 3 +lto = true + +[package.metadata.wasm-pack.profile.debug] +wasm-opt = ["-O4"] + +[package.metadata.wasm-pack.profile.release] +wasm-opt = ["-O4"] \ No newline at end of file diff --git a/wasm/rust-toolchain b/wasm/rust-toolchain new file mode 100644 index 000000000..467f338ce --- /dev/null +++ b/wasm/rust-toolchain @@ -0,0 +1 @@ +nightly-2022-12-12 \ No newline at end of file diff --git a/wasm/src/account/view_key.rs b/wasm/src/account/view_key.rs index 31f622711..bc9a42fb8 100644 --- a/wasm/src/account/view_key.rs +++ b/wasm/src/account/view_key.rs @@ -80,21 +80,15 @@ mod tests { use wasm_bindgen_test::*; - const OWNER_PLAINTEXT: &str = r"{ - owner: aleo1y50whk20gjtltkte2qcqz9dd6uaet8thhlj3t8utewp0j3hhmg8qae7s5a.public, - gates: 1159017656332810u64.public, - a: 6875465154712544327395236939215127424077297244802949502285127742492653680374field.private, - b: 603076889203566020456049671526074557206943911693533670547825725507132399266scalar.private, - _nonce: 1635890755607797813652478911794003479783620859881520791852904112255813473142group.public -}"; - const OWNER_CIPHERTEXT: &str = "record1qqj3a67efazf0awe09grqqg44htnh9vaw7l729vl309c972x7ldquqq2k2cax8s7qsqqyqtpgvqqyqsq4seyrzvfa98fkggzccqr68af8e9m0q8rzeqh8a8aqql3a854v58sgrygdv4jn9s8ckwfd48vujrmv0rtfasqh8ygn88ch34ftck8szspvfpsqqszqzvxx9t8s9g66teeepgxmvnw5ymgapcwt2lpy9d5eus580k08wpq544jcl437wjv206u5pxst6few9ll4yhufwldgpx80rlwq8nhssqywmfsd85skg564vqhm3gxsp8q6r30udmqxrxmxx2v8xycdg8pn5ps3dhfvv"; - const OWNER_VIEW_KEY: &str = "AViewKey1ghtvuJQQzQ31xSiVh6X1PK8biEVhQBygRGV4KdYmq4JT"; + const OWNER_PLAINTEXT: &str = "{\n owner: aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px.private,\n microcredits: 374999900000000u64.private,\n _nonce: 2740969152411805314773998757266754905498340517856884701781803565459552168415group.public\n}"; + const OWNER_CIPHERTEXT: &str = "record1qyqspsy0qghu8wqmf8wq2w4ccqqg8zsgxc3ge2znf4uklh8tutq2swgqqyxx66trwfhkxun9v35hguerqqpqzq9c6u30j7srax79wdvdqt2ytpne4vyvae6z9fq85rs09nj2f72uqm0kn9tx5t3znnj7hrqffzdcquacgyrqdfuuum2km7wvxcmy258svvkjzsh"; + const OWNER_VIEW_KEY: &str = "AViewKey1mSnpFFC8Mj4fXbK5YiWgZ3mjiV8CxA79bYNa8ymUpTrw"; const NON_OWNER_VIEW_KEY: &str = "AViewKey1e2WyreaH5H4RBcioLL2GnxvHk5Ud46EtwycnhTdXLmXp"; #[wasm_bindgen_test] pub fn test_from_private_key() { - let given_private_key = "APrivateKey1zkp4RyQ8Utj7aRcJgPQGEok8RMzWwUZzBhhgX6rhmBT8dcP"; - let given_view_key = "AViewKey1i3fn5SECcVBtQMCVtTPSvdApoMYmg3ToJfNDfgHJAuoD"; + let given_private_key = "APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH"; + let given_view_key = "AViewKey1mSnpFFC8Mj4fXbK5YiWgZ3mjiV8CxA79bYNa8ymUpTrw"; let private_key = PrivateKey::from_string(given_private_key).unwrap(); let view_key = ViewKey::from_private_key(&private_key); assert_eq!(given_view_key, view_key.to_string()); diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 762d731eb..46981a1ad 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -20,4 +20,10 @@ pub use account::*; pub mod record; pub use record::*; +pub mod program; +pub use program::*; + pub(crate) mod types; + +#[cfg(feature = "frontend-parallel")] +pub use wasm_bindgen_rayon::init_thread_pool; \ No newline at end of file diff --git a/wasm/src/program/decrypt.rs b/wasm/src/program/decrypt.rs new file mode 100644 index 000000000..bc351fe0b --- /dev/null +++ b/wasm/src/program/decrypt.rs @@ -0,0 +1,302 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use std::str::FromStr; + +use crate::{ + account::ViewKey, + types::{ + TransitionNative, + CurrentNetwork, ProgramIDNative, CiphertextNative, IdentifierNative + } +}; +use snarkvm_console::{prelude::Network, types::{U16, Field, Group}, program::ToBits}; +use snarkvm_synthesizer::{Input, Output}; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub struct DecryptTransition {} + +#[wasm_bindgen] +impl DecryptTransition { + pub fn owns_transition( + view_key: ViewKey, + tpk_str: &str, + tcm_str: &str, + ) -> Result { + console_error_panic_hook::set_once(); + + let tpk = Group::::from_str(tpk_str) + .map_err(|_| "Could not deserialize transition public key".to_string())?; + + let tcm = Field::::from_str(tcm_str) + .map_err(|_| "Could not deserialize transition commitment".to_string())?; + + let scalar = *view_key; + let tvk = (tpk * *scalar).to_x_coordinate(); + + let tcm_derived = CurrentNetwork::hash_psd2(&[tvk]) + .map_err(|_| "Could not deserialize transition".to_string())?; + + return Ok(tcm == tcm_derived); + } + + pub fn decrypt_ciphertext( + view_key: ViewKey, + ciphertext_str: &str, + tpk_str: &str, + program_id: &str, + function_name_str: &str, + index: usize, + ) -> Result { + console_error_panic_hook::set_once(); + + let tpk = Group::::from_str(tpk_str) + .map_err(|_| "Could not deserialize transition public key".to_string())?; + + let program_id = ProgramIDNative::from_str(program_id) + .map_err(|_| "Could not deserialize program id".to_string())?; + + let function_name = IdentifierNative::from_str(function_name_str) + .map_err(|_| "Could not deserialize function name".to_string())?; + + let scalar = *view_key; + let tvk = (tpk * *scalar).to_x_coordinate(); + + let function_id = CurrentNetwork::hash_bhp1024( + &(U16::::new(CurrentNetwork::ID), program_id.name(), program_id.network(), function_name).to_bits_le(), + ).map_err(|_| "Could not create function id".to_string())?; + + let index_field = Field::from_u16(u16::try_from(index).unwrap()); + let ciphertext_view_key = CurrentNetwork::hash_psd4(&[function_id, tvk, index_field]) + .map_err(|_| "Could not create ciphertext view key".to_string())?; + + let ciphertext = CiphertextNative::from_str(ciphertext_str) + .map_err(|_| "Could not deserialize ciphertext".to_string())?; + + let plaintext = ciphertext.decrypt_symmetric(ciphertext_view_key) + .map_err(|_| "Could not decrypt ciphertext".to_string())?; + + Ok(plaintext.to_string()) + } + + pub fn decrypt_transition( + view_key: ViewKey, + transition_str: &str + ) -> Result { + console_error_panic_hook::set_once(); + + let transition: TransitionNative = serde_json::from_str(transition_str) + .map_err(|_| "Could not deserialize transition".to_string())?; + + let scalar = *view_key; + let tvk = (*transition.tpk() * *scalar).to_x_coordinate(); + + let function_id = CurrentNetwork::hash_bhp1024( + &(U16::::new(CurrentNetwork::ID), transition.program_id().name(), transition.program_id().network(), transition.function_name()).to_bits_le(), + ).map_err(|_| "Could not create function id".to_string())?; + + let mut decrypted_inputs: Vec> = vec![]; + let mut decrypted_outputs: Vec> = vec![]; + + for (index, input) in transition.inputs().iter().enumerate() { + if let Input::Private(id, ciphertext_option) = input { + if let Some(ciphertext) = ciphertext_option { + let index_field = Field::from_u16(u16::try_from(index).unwrap()); + let input_view_key = CurrentNetwork::hash_psd4(&[function_id, tvk, index_field]) + .map_err(|_| "Could not create input view key".to_string())?; + let plaintext = ciphertext.decrypt_symmetric(input_view_key).unwrap(); + decrypted_inputs.push(Input::Public(*id, Some(plaintext))); + } else { + decrypted_inputs.push(input.clone()); + } + } else { + decrypted_inputs.push(input.clone()); + } + } + + let num_inputs = transition.inputs().len(); + for (index, output) in transition.outputs().iter().enumerate() { + if let Output::Private(id, ciphertext_option) = output { + if let Some(ciphertext) = ciphertext_option { + let index_field = Field::from_u16(u16::try_from(num_inputs + index).unwrap()); + let output_view_key = CurrentNetwork::hash_psd4(&[function_id, tvk, index_field]) + .map_err(|_| "Could not create output view key".to_string())?; + let plaintext = ciphertext.decrypt_symmetric(output_view_key).unwrap(); + decrypted_outputs.push(Output::Public(*id, Some(plaintext))); + } else { + decrypted_outputs.push(output.clone()); + } + } else { + decrypted_outputs.push(output.clone()); + } + } + + let decrypted_transition = TransitionNative::new( + *transition.program_id(), + *transition.function_name(), + decrypted_inputs, + decrypted_outputs, + transition.finalize().cloned(), + transition.proof().clone(), + *transition.tpk(), + *transition.tcm() + ).unwrap(); + + let transition_output = serde_json::to_string(&decrypted_transition) + .map_err(|_| "Could not serialize decrypted transition".to_string())?; + + Ok(transition_output) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + use wasm_bindgen_test::*; + + const VIEW_KEY: &str = "AViewKey1nPQW8P83ajkMBHQwYjbUfjGHVSkBQ5wctpJJmQvW1SyZ"; + const INCORRECT_VIEW_KEY: &str = "AViewKey1o8Hqq4tVbVMeeGtkEGUR7ULghFN8j89sqNQKYRZfe21u"; + const TRANSITION_VIEW_KEY: &str = "AViewKey1mSnpFFC8Mj4fXbK5YiWgZ3mjiV8CxA79bYNa8ymUpTrw"; + const TRANSITION: &str = r#" + { + "id": "as1pe954nkrsz4ztq7tphfug0cxtk4t0v5nnh885llkxufkckc0pcqq64fdjh", + "program": "credits.aleo", + "function": "transfer", + "inputs": [ + { + "type": "record", + "id": "7627242362896255517779759121644670167065542804779447008052019369271498021878field", + "tag": "7326825649979738473754819542510294000608550604334299567498630301585328020355field" + }, + { + "type": "private", + "id": "5890350227539634203276798567594921209939645071583932668707733854543695228358field", + "value": "ciphertext1qgqz2ypza9srfjnncjzz3hegltwmk0y348ufmklcuqwep2u9wnsqwqkrgx49dn0x78uqypznmyv8r80zwkte9rkfucv7fk4hw7w5s86dzyjmktp7" + }, + { + "type": "private", + "id": "3523824429192332435402492789955521910058950257573863610460494169456702420796field", + "value": "ciphertext1qyqfuz7006rcq9utzdsthdxqv4ra59u58wuggcacv44ka5uv7gyjcrsfh5xwh" + } + ], + "outputs": [ + { + "type": "record", + "id": "8375863992930925508608168893083821026035462437311607208725719081756051927038field", + "checksum": "327996249778261324588393772992776501551729208590293775377741829891566277743field", + "value": "record1qyqsqv0te3n9fws54jjywmrp36lc8l5gxgzyc9anjk30qsf7h45nfvgpqyxx66trwfhkxun9v35hguerqqpqzq8hd7es9dptx8l6ldn7u536g3hefvl03e6ztrufgk97ekf0us6azgl65lhfgcm4jf7fua2pcc2asy7r46rzv7eefvc8yrs39sgadue3zkl3emg" + }, + { + "type": "record", + "id": "3831168224702324801478452706121992429555677457517630037556628292830553507758field", + "checksum": "104402939347002555939092140274082734465350067270030368157770539944634402431field", + "value": "record1qyqspsy0qghu8wqmf8wq2w4ccqqg8zsgxc3ge2znf4uklh8tutq2swgqqyxx66trwfhkxun9v35hguerqqpqzq9c6u30j7srax79wdvdqt2ytpne4vyvae6z9fq85rs09nj2f72uqm0kn9tx5t3znnj7hrqffzdcquacgyrqdfuuum2km7wvxcmy258svvkjzsh" + } + ], + "proof": "proof1qqqqzqqqqqqqqqqqjgn70r0h5xcsysua8uve5wk400ash3ry6dwr3jjmeft5dmmql03ju0memtrwzppfsyl9x25v6svgrled6hd4s2887yz6wdde7fmv3kwlrdjx8kpvzq5asy02sljyc87ya7me3h5nkh3davwqklw6m2qzszt850x7jq0kt45zghwah6kalw7ufdh2v83jcrcwcpcwwa0m44sestdagm0z7hqe20zlfszva22kfqgpvnj9mavgqw2v5rmeeyz8hmn2j29npkvgteg0447zh6c097tx4dr2vmu2n5ts67xqu83058sjus3srrdgcypql8mymv7rhg580m5gckc4vnwjm2a53vg9sgqmyahs4fhmm0t0atyp9gjvflpt76d2nnsaqyqntm08rmtg0mwzajy2lpyfgq0r0gwq6pqcraty4623uyrzz8036np4clx3ak54qdlfamprav0chq95d696hsy4sdpsfphxuzq5mmehl0pjgk3f7wuvtjshz9dyrnrcwggnmjdqw965fmnjhlxv86ddruqj3cur9r38g2v4evaf2n5clr0844aek7j2gvz4zgshfddlkrg92wzk4yfwdjrwuvmpv77ss2f3efypelqu8sjp23fk93ygdads9lqtz8ghggdy5uhe9j7cyrg2ug4ghww9vvfljk2rgk04sfm23n8j474gzsmzz0nptrtdqmr2afddp5acssa5twxlcpf6vcghssrdan52wrykz5evryzvarw0xj9y0zf2ddarqxqfv2rcjfey9ur7tmaeh2qvqv8z9ggg8vtajql6vj2vuw5shmxsjahcq2ve7m3m3s8a30vy0qx47u263g77hz448mxug4r99vfgkpggv7rysklv0e9l40nt20uvnkuepeftgqwlz7t436z93fpq5qadxsr2tl93t87czw68h6nsglh9xxnenasa2f68vl7pvqahnjlyatcvzyytqxrglvgax9525hwvn939k9jtxzjeh97chr07qgvsp6f007c3p7hdca6cm7ss7wmdrefehzzpj4rpj30cnu2rhdce35ku3y640avsxlujsxnfs69g32q3nlqe7tlcka9zkmeurxx3fcq054sseehe2kqjr2tfdwmgfzgj28vynw4nxq54pvmpgkj53asfnt25yz250lmx0vzqyqqqqqqqqqqq9c4hem5wef967dqy4spcypsr8kwhnmxp35zlrdgq6rwejyqej2l2h6w2lnc7ttw2qxlj8shfju5czqwrcnaj00ky0yc98jck2rk43upw4gzxk6l866n0mh68q0vjalg0qd7tvlu4an04s3u799u28vct6wwm2gn0r5lpcv5jttds6ffw6ykkq6g42yvlam6zreceeqwqz25mrqqqqqppqwa5", + "tpk": "853764860907185272244987221391264508066723405990098126446569313951469774602group", + "tcm": "2890501131780933954363007654088502278361631362478553633880506988907453958068field" + } + "#; + + #[wasm_bindgen_test] + fn test_decrypt_transition() { + let view_key = ViewKey::from_str(TRANSITION_VIEW_KEY).unwrap(); + + let decrypted_transition_str = DecryptTransition::decrypt_transition(view_key, TRANSITION).unwrap(); + + let decrypted_transition: TransitionNative = serde_json::from_str(&decrypted_transition_str.clone()).unwrap(); + let public_input = decrypted_transition.inputs().into_iter().skip(1).next().unwrap(); + if let Input::Public(_id, plaintext_option) = public_input { + let plaintext = plaintext_option.as_ref().unwrap(); + assert_eq!(plaintext.to_string(), "aleo146dx5e4nssf49t0aq9qljk474kqxk848tl05m8w84vc0jqa30spqf4me04"); + } else { + panic!("Expected public input"); + } + + // let public_output = decrypted_transition.outputs().into_iter().next().unwrap(); + // if let Output::Public(_id, plaintext_option) = public_output { + // let plaintext = plaintext_option.as_ref().unwrap(); + // assert_eq!(plaintext.to_string(), "100000000u64"); + // } else { + // panic!("Expected public output"); + // } + } + + #[wasm_bindgen_test] + fn test_decrypt_ciphertext_input() { + let view_key = ViewKey::from_str(VIEW_KEY).unwrap(); + + // Try decrypting private input + let plaintext = DecryptTransition::decrypt_ciphertext( + view_key, + "ciphertext1qyq2786j69kjqmwz7lk9cn3glyq2w34j6zhlvxum6u9xkfk76hmd2rgg34kev", + "3681563105640905751787370687361466941855498391730203508101562167054325552256group", + "helloworld.aleo", + "main", + 1 + ).unwrap(); + + assert_eq!(plaintext, "2u32"); + } + + #[wasm_bindgen_test] + fn test_decrypt_ciphertext_output() { + let view_key = ViewKey::from_str(VIEW_KEY).unwrap(); + + // Try decrypting private output + let plaintext = DecryptTransition::decrypt_ciphertext( + view_key, + "ciphertext1qyqw68078jwlvz6v2wynue3g3dndyv0ydqutlmn99sfashquhkf52zql6xu7r", + "3681563105640905751787370687361466941855498391730203508101562167054325552256group", + "helloworld.aleo", + "main", + 2 + ).unwrap(); + + assert_eq!(plaintext, "3u32"); + } + + #[wasm_bindgen_test] + fn test_owns_transition_true() { + let view_key = ViewKey::from_str(VIEW_KEY).unwrap(); + + let owns_transition = DecryptTransition::owns_transition( + view_key, + "3681563105640905751787370687361466941855498391730203508101562167054325552256group", + "3205548165782039452146864733009325261935114902820697593223360259711032449007field" + ).unwrap(); + + assert!(owns_transition); + } + + #[wasm_bindgen_test] + fn test_owns_transition_false() { + let view_key = ViewKey::from_str(INCORRECT_VIEW_KEY).unwrap(); + + let owns_transition = DecryptTransition::owns_transition( + view_key, + "3681563105640905751787370687361466941855498391730203508101562167054325552256group", + "3205548165782039452146864733009325261935114902820697593223360259711032449007field" + ).unwrap(); + + assert!(!owns_transition); + } +} \ No newline at end of file diff --git a/wasm/src/program/intermediate_transaction.rs b/wasm/src/program/intermediate_transaction.rs new file mode 100644 index 000000000..90924d48a --- /dev/null +++ b/wasm/src/program/intermediate_transaction.rs @@ -0,0 +1,28 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::types::{ + InputIDNative, + TransitionNative, +}; + +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct IntermediateTransaction { + pub transition: TransitionNative, + pub input_ids: Vec +} \ No newline at end of file diff --git a/wasm/src/program/mod.rs b/wasm/src/program/mod.rs new file mode 100644 index 000000000..3f8a54315 --- /dev/null +++ b/wasm/src/program/mod.rs @@ -0,0 +1,33 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +pub mod proving_key; +pub use proving_key::*; + +pub mod verifying_key; +pub use verifying_key::*; + +pub mod program; +pub use program::*; + +pub mod intermediate_transaction; +pub use intermediate_transaction::*; + +pub mod transaction; +pub use transaction::*; + +pub mod decrypt; +pub use decrypt::*; \ No newline at end of file diff --git a/wasm/src/program/program.rs b/wasm/src/program/program.rs new file mode 100644 index 000000000..31f3dcf25 --- /dev/null +++ b/wasm/src/program/program.rs @@ -0,0 +1,81 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::types::ProgramNative; + +use core::{ops::Deref, str::FromStr}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct Program(ProgramNative); + +#[wasm_bindgen] +impl Program { + /// Get the id of the program + pub fn id(&self) -> String { + self.0.id().to_string() + } + + /// Create a program from a string representation + /// + /// This function will fail if the text is not a valid program + pub fn from_string(program: &str) -> Result { + Self::from_str(program).map_err(|_| "Invalid program".to_string()) + } + + /// Get a string representation of the program + #[allow(clippy::inherent_to_string_shadow_display)] + pub fn to_string(&self) -> String { + self.0.to_string() + } + + /// Get the default credits program + /// + /// This function shouldn't fail as the credits program is always defined + pub fn credits() -> Result { + let credits_program = ProgramNative::credits().map_err(|_| "Could not load credits program".to_string())?; + Ok(Self(credits_program)) + } +} + +impl From for Program { + fn from(program: ProgramNative) -> Self { + Self(program) + } +} + +impl From for ProgramNative { + fn from(program: Program) -> Self { + program.0 + } +} + +impl FromStr for Program { + type Err = anyhow::Error; + + fn from_str(program: &str) -> Result { + Ok(Self(ProgramNative::from_str(program)?)) + } +} + +impl Deref for Program { + type Target = ProgramNative; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} \ No newline at end of file diff --git a/wasm/src/program/proving_key.rs b/wasm/src/program/proving_key.rs new file mode 100644 index 000000000..f16cead19 --- /dev/null +++ b/wasm/src/program/proving_key.rs @@ -0,0 +1,91 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::{ + types::{ProvingKeyNative, ToBytes, FromBytes}, +}; + +use std::{ops::Deref}; + +use wasm_bindgen::prelude::*; +use web_sys::console; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct ProvingKey(ProvingKeyNative); + +#[wasm_bindgen] +impl ProvingKey { + #[wasm_bindgen] + pub fn from_bytes(bytes: &[u8]) -> ProvingKey { + // console_error_panic_hook::set_once(); + ProvingKeyNative::from_bytes_le(bytes).map(|proving_key| Self(proving_key)) + .expect("Failed to deserialize prover key") + } + + #[wasm_bindgen] + pub fn to_randomness_bytes(&self) -> Result, String> { + console_error_panic_hook::set_once(); + self.0.circuit_commitment_randomness.to_bytes_le().map_err(|_| "Failed to serialize prover key".to_string()) + } + + #[wasm_bindgen] + pub fn to_committer_bytes(&self) -> Result, String> { + console_error_panic_hook::set_once(); + self.0.committer_key.to_bytes_le().map_err(|_| "Failed to serialize prover key".to_string()) + } + + #[wasm_bindgen] + pub fn to_verifying_bytes(&self) -> Result, String> { + console_error_panic_hook::set_once(); + self.0.circuit_verifying_key.to_bytes_le().map_err(|_| "Failed to serialize prover key".to_string()) + } + + #[wasm_bindgen] + pub fn to_bytes(&self) -> Result, String> { + console_error_panic_hook::set_once(); + self.0.to_bytes_le().map_err(|_| "Failed to serialize prover key".to_string()) + } +} + +impl Deref for ProvingKey { + type Target = ProvingKeyNative; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for ProvingKeyNative { + fn from(proving_key: ProvingKey) -> ProvingKeyNative { + proving_key.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use wasm_bindgen_test::*; + + #[wasm_bindgen_test] + fn test_deserialize_serialize_key_wasm() { + let transfer_bytes = include_bytes!(concat!(env!("HOME"), "/.aleo/resources/inclusion.prover.209da1d")).to_vec(); + let proving_key = ProvingKey::from_bytes(transfer_bytes.clone()); + let bytes = proving_key.to_bytes().unwrap(); + assert!(transfer_bytes.eq(&bytes)); + } +} \ No newline at end of file diff --git a/wasm/src/program/transaction.rs b/wasm/src/program/transaction.rs new file mode 100644 index 000000000..e1e73aeb1 --- /dev/null +++ b/wasm/src/program/transaction.rs @@ -0,0 +1,290 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::{ + Program, + ProvingKey, + VerifyingKey, + IntermediateTransaction, + account::PrivateKey, + types::{ + Aleo, + ExecutionNative, + InclusionNative, + ProcessNative, + ProgramNative, + ProvingKeyNative, + VerifyingKeyNative, + StatePathNative, + StateRootNative, + TransactionNative, + FeeNative, + IdentifierNative + }, RecordPlaintext +}; +use std::collections::HashMap; + +use std::str::FromStr; +use snarkvm_console::program::Record; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub struct TransactionBuilder {} + +#[wasm_bindgen] +impl TransactionBuilder { + pub fn build_transition( + program: Program, + function_name: &str, + inputs: &str, // https://github.com/rustwasm/wasm-bindgen/issues/111 + private_key: PrivateKey, + proving_key: ProvingKey + ) -> Result { + console_error_panic_hook::set_once(); + let inputs: Vec = serde_json::from_str(inputs) + .map_err(|_| "Could not deserialize inputs".to_string())?; + + // Get the function identifier + let program_native = ProgramNative::from(program); + let function_identifier = IdentifierNative::from_str(function_name) + .map_err(|_| "Could not get function identifer".to_string())?; + if !program_native.contains_function(&function_identifier) { + return Err(format!("Function: {:?} not found", function_identifier)) + } + + // Create the process with only the credits program by default + let mut process = ProcessNative::load_wasm().map_err(|_| "Could not initialize wasm".to_string())?; + + // Check if the process contains the program, if not, add it + if !process.contains_program(program_native.id()) { + process.add_program(&program_native).map_err(|_| "Could not add program".to_string())?; + } + + // Insert the proving key + process.insert_proving_key(program_native.id(), &function_identifier, ProvingKeyNative::from(proving_key)) + .map_err(|_| "Could not insert proving key".to_string())?; + + // Generate the authorization + let rng = &mut rand::thread_rng(); + let authorization = + process.authorize::(&private_key, program_native.id(), function_name, inputs.iter(), rng) + .map_err(|thing| { + println!("{:?}", thing); + return "Could not generate authorization".to_string(); + })?; + + // Get the input_ids, necessary to reconstruct the inclusion proof + let next = authorization.peek_next().unwrap(); + let input_ids = next.input_ids().to_vec(); + + // Generate the execution + let (_, execution, _, _) = process.execute::(authorization, rng) + .map_err(|_| "Could not complete program execution".to_string())?; + + // Get the transition from the execution + let mut transitions = execution.transitions(); + let transition = transitions.next().unwrap().to_owned(); + let intermediate_transaction = IntermediateTransaction { + transition, + input_ids + }; + let intermediate_transaction = serde_json::to_string(&intermediate_transaction) + .map_err(|_| "Could not serialize intermediate transaction".to_string())?; + + Ok(intermediate_transaction) + + } + + pub fn build_transaction( + inclusion_key: ProvingKey, + intermediate_transactions: &str, + state_root: &str, + commitment_map: &str + ) -> Result { + console_error_panic_hook::set_once(); + + // Create Inclusion and Execution from all IntermediateTransactions + let mut inclusion = InclusionNative::new(); + let mut execution = ExecutionNative::new(); + + let intermediate_transactions: Vec = serde_json::from_str(intermediate_transactions) + .map_err(|_| "Could not deserialize intermediate transactions".to_string())?; + + for IntermediateTransaction { transition, input_ids } in &intermediate_transactions { + let transition = transition.to_owned(); + inclusion.insert_transition(&input_ids, &transition).unwrap(); + execution.push(transition); + } + + // Parse state root and state paths + let global_state_root = StateRootNative::from_str(state_root).unwrap(); + let default_map: HashMap = HashMap::new(); + let commitment_to_state_path: HashMap = serde_json::from_str(commitment_map).unwrap_or(default_map); + + // Prepare the assignments. + let (assignments, _) = inclusion + .prepare_execution_stateless(&execution, global_state_root, commitment_to_state_path).unwrap(); + + // Compute the inclusion proof and update the execution. + let rng = &mut rand::thread_rng(); + let execution = inclusion + .prove_execution_stateless::(inclusion_key.into(), execution, &assignments, global_state_root, rng).unwrap(); + + let tx = TransactionNative::from_execution(execution, None).unwrap(); + Ok(tx.to_string()) + } + + pub fn add_fee_to_transaction( + transaction_string: &str, + fee_string: &str + ) -> Result { + console_error_panic_hook::set_once(); + // Parse Transaction + let mut transaction = TransactionNative::from_str(transaction_string).unwrap(); + let mut fee = FeeNative::from_str(fee_string).unwrap(); + + if let TransactionNative::Execute(id, execution, _) = transaction { + let tx = TransactionNative::from_execution(execution, Some(fee)).unwrap(); + Ok(tx.to_string()) + } else { + return Err("Transaction is not an execution".to_string()); + } + } + + pub fn verify_transaction( + transaction_string: &str, + program: Program, + function_name: &str, + function_verifying_key: VerifyingKey, + inclusion_key: VerifyingKey, + verify_inclusion: bool, + verify_execution: bool + ) -> Result { + console_error_panic_hook::set_once(); + // Parse Transaction + let transaction = TransactionNative::from_str(transaction_string).unwrap(); + + // Get the function identifier + let program_native = ProgramNative::from(program); + let function_identifier = IdentifierNative::from_str(function_name) + .map_err(|_| "Could not get function identifer".to_string())?; + if !program_native.contains_function(&function_identifier) { + return Err(format!("Function: {:?} not found", function_identifier)) + } + + // Create the process with only the credits program by default + let mut process = ProcessNative::load_wasm().map_err(|_| "Could not initialize wasm".to_string())?; + + // Check if the process contains the program, if not, add it + if !process.contains_program(program_native.id()) { + process.add_program(&program_native).map_err(|_| "Could not add program".to_string())?; + } + + // Insert the verifying key + process.insert_verifying_key(program_native.id(), &function_identifier, VerifyingKeyNative::from(function_verifying_key)) + .map_err(|_| "Could not insert transfer verifying key".to_string())?; + + match transaction { + TransactionNative::Deploy(_, _, _, _) => { + panic!("Cannot verify Deploy Transactions"); + } + TransactionNative::Execute(_, execution, _) => { + if verify_execution { + process.verify_execution::(&execution) + .map_err(|_| "Failed to verify execution".to_string())?; + } + if verify_inclusion { + InclusionNative::verify_execution_stateless(&execution, VerifyingKeyNative::from(inclusion_key)) + .map_err(|_| "Failed to verify inclusion".to_string())?; + } + } + } + + Ok("Transaction verified".to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use wasm_bindgen_test::*; + use web_sys::console; + + // const PRIVATE_KEY: &str = "APrivateKey1zkpDKDJELtg3GN29R2UPihgsucvYSkb7BzEYDRkJtZcwhj8"; + // const PRIVATE_KEY: &str = "APrivateKey1zkpEkwRohuPgJGxFS7TECc6nEzvNa1P7vP38mq7RkhS6RCG"; + // const PRIVATE_KEY: &str = "APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH"; + const PRIVATE_KEY: &str = "APrivateKey1zkp8UsqkCvrUoFaCn1Dw9WJG69hp8TLFgT1V99cuZWVoDKx"; + const OWNER_PLAINTEXT1: &str = r"{ owner: aleo146dx5e4nssf49t0aq9qljk474kqxk848tl05m8w84vc0jqa30spqf4me04.private, microcredits: 101u64.private, _nonce: 2036393439745953531101794606409563566245421800022328395850697982644162839463group.public}"; + // const OWNER_PLAINTEXT1: &str = r"{ owner: aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px.private, microcredits: 375000000000000u64.private, _nonce: 3929214896371155671696476761462680699003730187884776587690604310763551537209group.public}"; + // const OWNER_PLAINTEXT1: &str = r"{ owner: aleo1mc6h9k9g03hfkrh93wm6vlew6q2ehzwalqutzjx6hp5mdcv9rsyq2w3alz.private, gates: 9973u64.private, _nonce: 1157538218493794217455834413151916695596644156738232294925137030650794330428group.public}"; + const OWNER_PLAINTEXT1_COMMITMENT: &str = r"605538192287731854742364189642613370746132375889525872894501892977418029640field"; + const OWNER_PLAINTEXT1_PATH: &str = r"path1qqqd4vjjgfd05ekjmd02r74pxd7rqjsu2n3a9rnutkc6x5c3yhj6szklquqqqqqqqqqr4hq4tv6w8qp64680gfnq69tvdr0unup88k5sgum5ynru8f7zqpx6z4t3pxwm2zh2c9n8jhm9f9nat86kdx2yf5lfdl8kr0p9rh3fq347xs7al64hvdjuetejauufsfhvrvzz429kcmcavjs9229ctedssw8ucpfq88q4jkf083fwp64nwf6eq06wj0vlqa2s87c4vudemsqy3facnk8c6xwskfg23h6xctfca2r28echq935pzjt8n6upgv9ls9zm4ll46tsszsxkdg3hw0vl6ah8vmvrh7g2eejfjeju6c6dlt7gy9jsvfa60yjq5tft7zt6gnsz4flegx50dgsluqwwv6w7hwpct99z2y8ftxn4pupqlvupt4jtjkv2zxkye0333ktmjfgz03f99xy03aqjzx4zmzemg6kyxugy97m6p9mlfkmp5xwz5udre5rh4rk40ezsrsftcghmjqf793nuq482m5uyznnegaq8v6tu4zxr78pyh23hug8jvqmut52jefmeqd8dnzsugx65fwhr3qmtfw8nw9am5kwwtnjyk4jsy5yzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qns27zmwr8z5y604wad5pcrjyx0xw0jsev8zmp92hetyf8nvepgqlrrj4qwaueef7jukyclk7xy5djeg3jqan4cpdnv69aa7az6tulssu4qm9lrx3fzgdqlpd7zfct94fyw63a2gzyglj72cx7rlyfmrlgrszqqqqqqqqqqqkrg383d3ctrsv3dn365v0hg3wmuj7frqzmuvldsj9mjcgllaqyqx8ce6fm5jhhfup3as6eg7m95h7hhd38f2m2e8w582lwzj253rkpqplxpvafj73f7kuymxn2lnhajfymjp7tg4r8xc8ltq70zgdwtcpvqcmhna74rpc8h4yt4f6g9uxdls83qr6cpvyymespsaahtpn0c9spsqqqqqqqqqqqqqhcewf768vg6pldnetgxf448sm9ecxd9vlzcp72d4nxqxlsx2vr5yzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzgg9v7559gaxswfjytkkhslq44kvj8ld2pj29xvvqdlsn6zez45pzumn3nfqsdylxcesax8zwvks7de3v0gw5ndttpd4l80ucku7mvp5qqqqqqqqqqqqyyzk022z5wng8yez9mttc0s26mxfrlk4qe9znxxqxlcfapv326qjzpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqfpq4n6js4r56pexg3w667ruzkkejgla4gxfg5e3sph7z0gty2ksyss2eafg236dqunyghdd0p7pttvey0765ry52vccqmlp859j9tgzqzqqqhgl59s8lcdezyqg4ylcvajkjwqkcv9dygxm23njmd9fvvmk30c9sxqqqqqqqqqqqe332uur0a63lncg7gw5nz5vqqkz3njajl9v4henfgjuuh3hjksr879j0kkkteaehcn9yfmmh5ny4j9vt8gqelnygdue682j97ka4yq099ryhtp3hk6f0mvcr5watm4ca7wg42sze6skdmsxt8jx8t72hq6zpt849p28f5rjv3za44u8c9ddny3lm2svj3fnrqr0uy7skg4dqgqqrqvqy3jnmdu3va9w68y6rcnlmvh26mhud86nqqs0v0p84nq7l7wu9vqg4sqmk7"; + + const RECIPIENT: &str = "aleo1nhdttzqjjj68qqjge68m7ugpz6d9dq30qxxngyg2qjr9f8hx4cgs42t7wp"; + const AMOUNT: &str = "97u64"; + const GLOBAL_STATE_ROOT: &str = "ar13manm2epykqtk0zxzcqa7nn3zc5z064lap6r2ys0t0l5t3uy9crsufrdj2"; + + // #[wasm_bindgen_test] + // fn test_build_transition() { + // // Prepare inputs to build transition + // let program = Program::credits().unwrap(); + // let function_name = "transfer"; + // let inputs = serde_json::to_string(&[ + // OWNER_PLAINTEXT1, + // RECIPIENT, + // AMOUNT + // ]).unwrap(); + // let private_key = PrivateKey::from_str(PRIVATE_KEY).unwrap(); + // let transfer_bytes = include_bytes!(concat!(env!("HOME"), "/.aleo/resources/transfer.prover.95214f1")).to_vec(); + // let transfer_proving_key = ProvingKey::from_bytes(transfer_bytes); + + // // Build transition + // let intermediate_transaction1 = TransactionBuilder::build_transition( + // program, + // function_name, + // &inputs, + // private_key, + // transfer_proving_key + // ).unwrap(); + + // console::log_1(&intermediate_transaction1.into()); + // } + + // #[wasm_bindgen_test] + // fn test_build_transaction() { + // // Prepare inputs to build transaction + // let intermediate_transaction1 = r#"{"transition":{"id":"as100gs7rlucq4zu7u3dlwys9vnep80ftwws2u2ausvzcpf2fesrgzsfuf9jv","program":"credits.aleo","function":"transfer","inputs":[{"type":"record","id":"5014771957006340580317363981373591084465734774693302641777058302177738009042field","tag":"1592215853668322267062146193964960404834934970523747812466009574754114740452field"},{"type":"private","id":"322815084863476371220771878109567628405323161045197678148136586030747914889field","value":"ciphertext1qgq9ya29q50jnxwspkwgr6g4cgvf87sw5j2hvk6x2zmkarg9xxauxqhyj3fh8xs0gjqfezfl689krqxj5th76uz075465mfjdvfh72tgpc3tan76"},{"type":"private","id":"2145739655038782315766524255894847900603699299809703897648490882673572222470field","value":"ciphertext1qyqrh2twkdal03adakvv4cl4lzrwu5wljxyms84js9s5h6l62ftevqcj2rk79"}],"outputs":[{"type":"record","id":"4069439388021451078269049650605705726761983682392111434935933144215765309236field","checksum":"1406934742874233776553884855777823800086998498181550189152055420777952320965field","value":"record1qyqspyrgflcgucsr59gqzqzegxf395wxhw0eq3kv63zsfa7y9sqd4tqsqyqspuv6ewd4qhz6p9r2nfakxmn2l2zfyqgsh6vh6p2d5q2650vxtjq8qzajnka4q5u50vfwdavv3qqwe2wnpsuymfxvzyazmejnjnuqgurswsfx9eh"},{"type":"record","id":"5420469059357958525128014207249608754218509899266503418642860591860771984738field","checksum":"980276437940144926956762218081372377044893877273476995664467211172445965935field","value":"record1qyqsp0lyytf9eym2xccvpcm45nyuymmksnvmlyvd6furxqx7rv8wfkssqyqspevvj0qamqf3rsz4sf67k7qppslfj9e3fwfzrfhmxuwz6rw8myc2qzz8gdp55x534a0e2haqg9jd960yyuhkcn09jgqddlu0fyumxmzsvrj4due"}],"proof":"proof1qqqqzqqqqqqqqqqqkvuv2w8r0npu43mp8s7p9sh48cjssqq5q6ya4x9ryg4fu7dl0x6xsmqqdnjd7s9e3yu0n6yzvv5czgvaghn8vfurfcm6dlfgwzp3lk8un8wzshhleqpdxm8l04e86p3n8ux8kwn42vaz6kgz7ngnahvssq7er0szz4ku9q2xdz2pz58fhcuka5k4ff9lsmjax273maz9ph2tf0mvfzdh8zm0snh6v4xj7pls2qgptdaxeyqg8x57n7rehkywucu38mup6gnm6f700j7x8wak7evtsw8juqqxswxdh525ml6spr5smsncp03emkk85pt52jtdt8qqcmttg3rxj2uvjv2km4r7acxuyqca4f632fksax6ed287c4khjwucqvvjq8ks5k5atpdftwu82vxmu65pxsn494p9gsthhg0j4kpqrk30cd4pxkjnwrjewltuvp7jztfd4dppyqwss3yd26vecdad3rt6ez4gqhx9tn776m4grugc3ztfg2r2facr5mcw8uxwq963vc6pxngenzqp55q2j0y0j8rz62ry40ygxr72s6zk6hxdltfvmuxmlujuzkf5a09p8nre7slgxff4rwqelmfqd4jved5q4j542ddwlgp20qhsd8mnkdcckgvwrt6rv6a20rhutj72f5ns44tsxlztrdffj4lqycfy6qr7jaesr6zch4v9keullzuem4nz7rgs9rps8d3aywq8lu9pz7nprgkjjau6p3qh87gceqe6wtevss8wl0ppsx24nhppj8z4274wegs9te8eeekr9pl8ue2hy7war4smlksmdngsva9g5kjvm4h3046070enwemsduztlwwd08gxmaymwc8hrd485gqsp2nakpzjlaqdmv6q3w6f9usju4l760zgmzny7l9chfcfy8xekcgyysv4a3yvcnm84t0c7c8l4ef0afkp37409gctx6cg79z88h86wpce4tan5lecxaa4aqde8gay4wmdu4sywhdw32cnses8pdka9xhqp09uxrfndxj35ng0r0zj625t3ny2gp6990wwe5dsk2d8ng2j4ajsk097d5gjh0m3nzkng39sfrrrf6v3rjdc6mr2agn6clp09jmgzlqjy37y8p2rymn2nuw3aktznpy4kra58cdkfgfuvehpwg5hgq0g9c8syqqqqqqqqqqq6cac9vgjv8433sg7e522nz0dg379t955ft035ce8z7xe4h228dqajv9g6qlkwn8zjt6kgy0c7ragqq2matv09cpdyswjsknfd9g7srqm8dpfq5wjqxee6yavqlw08jc3qwwtahh9nnwav6cl4lhfstp3yezyu82m2068drjqqzkuy705mt8fwwdwdgpx2z2pljnal63zppm9vqqqqq2pftw6","tpk":"7232922488843750299609714637897998954390062332698850825353778535377930212519group","tcm":"2576677602366284087862363339085985775279049642524480921123773832178280700244field","fee":0},"input_ids":[{"type":"record","commitment":"605538192287731854742364189642613370746132375889525872894501892977418029640field","gamma":"5356502370233901355799069746156088185496903661954521847638241903524144982783group","serial_number":"5014771957006340580317363981373591084465734774693302641777058302177738009042field","tag":"1592215853668322267062146193964960404834934970523747812466009574754114740452field"},{"type":"private","id":"322815084863476371220771878109567628405323161045197678148136586030747914889field"},{"type":"private","id":"2145739655038782315766524255894847900603699299809703897648490882673572222470field"}]}"#; + // let intermediate_transaction1: IntermediateTransaction = serde_json::from_str(intermediate_transaction1).unwrap(); + // let inclusion_bytes = include_bytes!(concat!(env!("HOME"), "/.aleo/resources/inclusion.prover.209da1d")).to_vec(); + // let inclusion_proving_key = ProvingKey::from_bytes(inclusion_bytes); + // let intermediate_transactions = serde_json::to_string(&[ + // intermediate_transaction1 + // ]).unwrap(); + + // let mut commitment_map: HashMap = HashMap::new(); + // commitment_map.insert(OWNER_PLAINTEXT1_COMMITMENT.to_string(), StatePathNative::from_str(&OWNER_PLAINTEXT1_PATH).unwrap()); + // let commitment_map_serialized = serde_json::to_string(&commitment_map).unwrap(); + + // let transaction = TransactionBuilder::build_transaction( + // inclusion_proving_key, + // intermediate_transactions.as_str(), + // GLOBAL_STATE_ROOT, + // &commitment_map_serialized.as_str() + // ).unwrap(); + + // console::log_1(&transaction.into()); + // } +} \ No newline at end of file diff --git a/wasm/src/program/verifying_key.rs b/wasm/src/program/verifying_key.rs new file mode 100644 index 000000000..2e52f2aed --- /dev/null +++ b/wasm/src/program/verifying_key.rs @@ -0,0 +1,72 @@ +// Copyright (C) 2019-2023 Aleo Systems Inc. +// This file is part of the Aleo library. + +// The Aleo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Aleo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Aleo library. If not, see . + +use crate::{ + types::{VerifyingKeyNative, ToBytes, FromBytes}, +}; + +use std::{ops::Deref}; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct VerifyingKey(VerifyingKeyNative); + +#[wasm_bindgen] +impl VerifyingKey { + #[wasm_bindgen] + pub fn from_bytes(bytes: Vec) -> VerifyingKey { + console_error_panic_hook::set_once(); + let verifying_key = VerifyingKeyNative::from_bytes_le(&bytes); + Self(verifying_key.unwrap()) + } + + #[wasm_bindgen] + pub fn to_bytes(&self) -> Result, String> { + console_error_panic_hook::set_once(); + self.0.to_bytes_le().map_err(|_| "Failed to serialize prover key".to_string()) + } +} + +impl Deref for VerifyingKey { + type Target = VerifyingKeyNative; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for VerifyingKeyNative { + fn from(verifying_key: VerifyingKey) -> VerifyingKeyNative { + verifying_key.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use wasm_bindgen_test::*; + + #[wasm_bindgen_test] + fn test_deserialize_serialize_key_wasm() { + let transfer_bytes = include_bytes!(concat!(env!("HOME"), "/.aleo/resources/transfer.verifier.78aa4e5")).to_vec(); + let verifying_key = VerifyingKey::from_bytes(transfer_bytes.clone()); + let bytes = verifying_key.to_bytes().unwrap(); + assert!(transfer_bytes.eq(&bytes)); + } +} \ No newline at end of file diff --git a/wasm/src/record/record_plaintext.rs b/wasm/src/record/record_plaintext.rs index 08795dbb6..2a43a8153 100644 --- a/wasm/src/record/record_plaintext.rs +++ b/wasm/src/record/record_plaintext.rs @@ -42,11 +42,6 @@ impl RecordPlaintext { self.0.to_string() } - /// Returns the amount of gates in the record - pub fn gates(&self) -> u64 { - ***self.0.gates() - } - /// Attempt to get the serial number of a record to determine whether or not is has been spent #[wasm_bindgen(js_name = serialNumberString)] pub fn serial_number_string( @@ -110,12 +105,6 @@ mod tests { assert_eq!(record2.to_string(), expected_string); } - #[wasm_bindgen_test] - fn test_gates_from_string() { - let record = RecordPlaintext::from_string(RECORD).unwrap(); - assert_eq!(record.gates(), 99); - } - #[wasm_bindgen_test] fn test_serial_number() { let pk = PrivateKey::from_string("APrivateKey1zkpDeRpuKmEtLNPdv57aFruPepeH1aGvTkEjBo8bqTzNUhE").unwrap(); diff --git a/wasm/src/types.rs b/wasm/src/types.rs index 57aa443a4..b03e65384 100644 --- a/wasm/src/types.rs +++ b/wasm/src/types.rs @@ -14,10 +14,32 @@ // You should have received a copy of the GNU General Public License // along with the Aleo library. If not, see . +use snarkvm_synthesizer::{ + Process as AleoProcess, + Program as AleoProgram, + Transaction as AleoTransaction, + Transition as AleoTransition, + Fee as AleoFee, + ProvingKey as AleoProvingKey, + VerifyingKey as AleoVerifyingKey, + Inclusion as AleoInclusion, + Execution as AleoExecution +}; use snarkvm_wasm::{ account::{Address, PrivateKey, Signature, ViewKey}, - network::Testnet3, - program::{Ciphertext, Identifier, Plaintext, ProgramID, Record}, + network::Testnet3 +}; +use snarkvm_console::{ + program::{ + Ciphertext, + Identifier as AleoIdentifier, + InputID as AleoInputID, + Plaintext, + ProgramID, + Record, + StatePath as AleoStatePath, + Network + } }; pub use aleo_rust::Encryptor; @@ -30,7 +52,22 @@ pub type SignatureNative = Signature; pub type ViewKeyNative = ViewKey; // Network types +pub type Aleo = snarkvm_wasm::AleoV0; pub type CurrentNetwork = Testnet3; +pub type ProvingKeyNative = AleoProvingKey; +pub type VerifyingKeyNative = AleoVerifyingKey; + +// Program types +pub type InputIDNative = AleoInputID; +pub type ProcessNative = AleoProcess; +pub type ProgramNative = AleoProgram; +pub type TransactionNative = AleoTransaction; +pub type TransitionNative = AleoTransition; +pub type FeeNative = AleoFee; +pub type StateRootNative = ::StateRoot; +pub type StatePathNative = AleoStatePath; +pub type InclusionNative = AleoInclusion; +pub type ExecutionNative = AleoExecution; // Record types pub type CiphertextNative = Ciphertext; @@ -39,5 +76,5 @@ pub type RecordCiphertextNative = Record; pub type RecordPlaintextNative = Record; // Utility types -pub type IdentifierNative = Identifier; +pub type IdentifierNative = AleoIdentifier; pub type ProgramIDNative = ProgramID; diff --git a/website/.babelrc b/website/.babelrc new file mode 100644 index 000000000..0960c0126 --- /dev/null +++ b/website/.babelrc @@ -0,0 +1,6 @@ +{ + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ] +} \ No newline at end of file diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 000000000..042d2916d --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,26 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +aleo-wasm +.eslintcache diff --git a/website/package.json b/website/package.json index 96124db9a..ea3953c5f 100644 --- a/website/package.json +++ b/website/package.json @@ -9,6 +9,8 @@ "antd": "^4.11.2", "axios": "^1.1.3", "babel-loader": "^8.2.3", + "babel-polyfill": "^6.26.0", + "comlink": "^4.4.1", "copy-to-clipboard": "^3.3.1", "gh-pages": "^3.1.0", "react": "^17.0.1", @@ -22,6 +24,7 @@ "@wasm-tool/wasm-pack-plugin": "^1.3.1", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.6.0", + "dexie": "^3.2.3", "html-webpack-plugin": "^5.5.0", "mini-css-extract-plugin": "^2.5.3", "style-loader": "^3.3.1", @@ -30,10 +33,7 @@ "webpack-dev-server": "^4.7.4" }, "scripts": { - "preinstall": "cd ../wasm && wasm-pack build", - "prestart": "yarn preinstall", - "prerestart": "yarn preinstall", - "start": "webpack-dev-server", + "start": "yarn upgrade @aleohq/wasm && webpack-dev-server", "build": "webpack --config webpack.config.js", "predeploy": "yarn build", "deploy": "gh-pages -d build", diff --git a/website/pkg/index.js b/website/pkg/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/website/public/logo192.png b/website/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..09489c843c245c83810a9366dd1229c25bfef8a0 GIT binary patch literal 12574 zcmY*=1ymeM)9CKvwgh(#u8X@a7Tk4lcMnc**WeZ`NP@crclQt=xD!I~;PANLf8Y1N zH*Yiv-WmybVVpISCfbmXFO8pfEzZNfK#MdW{{aejf0CZQEl>}5z zksiHP!Yp;)St%(2m|k&Y00Iyj0QV2e>kR-B0}%d$0|4?slKa?wH2-%Y&1H-E@D zOGh`SgP?>)Ix3S+nE(ZPdBHRTph$5*u$~2lISCx%uw4DZFX^?Hzw7=RRqdxWH}@|F ztY36Ez8ls!t@%|LX{|lj)!e@o&{N8msW*^!GhG;~_qO&;mzpGy%XUa%5Y(U{CU}P= zE=HY9n#3LOrqx+~rAvX0^il6kHOtSEc!+I;P;}5C&6ol`vsbC*-9>_wU6WK-nzlvz z9fj0KzLzZ+cdxh{*Zf+fR*u?8m|LK>?w@2OOt8T1f`=#iLVRs#5>ZV zW)&eH8IPsX5Vx(1f<6N~6ZBiD!mYqH1zr247}c$LIVh9TjA3NkP4T?t4e!TfJH7o) zdv2#Bw1@SQ?dP)=ri;?c+#*J^05N3FN=n<%##qF!28*KJQ!xnxBTu~o z2Q)gC;3U%EBy21Rgt@>0dbe`d$ln#uLfk0vDPLreV+<k4Nmau5{**_jL;cG>B3QH+S?5Uo)=WXI%n~J|OxYDWV zA|kffjol&la7Arg{XvdbyQL7ZeCPOd8l{BcQE_vVX^wCPcL-L7`&;hsIQ%^UNkvWi zntR4^(s_Dk*O$>wS3{q6yx#lKo`ZQ&A8E}Dp#vkj&;YLyhfug~e)=UyBpSvgRFoO0 zjd-aTCMtu{r2LI>@5=V#@fpdJ(C+O=pGSL&x&T-=xLQ&sPO7wtKV`McwO#2ii}+Ec*0SEn(OMX)KpL8!(d~iwk9jF& zF;@Y`_Z5l#{GWE-(<6^-)!p;?XYM$)CK-hZDM>*i9=>vFbt@RnyhvJ_A8<>$*G)~_ zSEBF-D5U)DG#n}fczPhlqHg{~+S_@H%WK*|6pDmy>=8eG=D*?5N&7Z{UA*kdQ-1wK z=*!SIWtf$101-*f%gL&qdi-gc8!Y|v~X zlji53xEsf`s!S=jfK=sxI#pr&u;ypG5T)lFHt8QDy5XoZLE<2Uf}oH&Lu9ZmaoAWx zkSA1{LhKHLBcM|=9?{hRi9CxW9wcW(ayBN|>@d@v|FWO?*knNB=64y+ss7Aqg>(s( zoWuy@+E%nm8xqqm=usnNafmQ|j`*z{STc_VR~Zv#}Ot@v!$s< zH5&#{>)$X(D@nF?7R~<2P=Yssgmk!ygi;Sd9Q)`H3({i}X^mRA%5J3bY}+*!ftvjN zP4JhZd!@bR`{O$LO`kxsatIAN?Jg|=DpzRl564~cc0CIJPv#!+v6%4{akSRT8iq{9 zj=~BAnXMn&lqc?0L2Pea%?@`kuN6oQkA$8x3q}KW@~Cxyz4mO3M2dx;x_C_Y@%gt# zyt``E@Hlb-nXU5g?Q#ujHwQf9Jxvy+srMrNax;~Ewkbwz_DIoDmRWG^fF|uIDUu^+ z2nY~hO61TZQ8&~pAfh9I0!PlBQ3j1*RBWnK(!PrIxHzTtZ(2|ui__+<;=MQW5m_G* zkp6qPw56td(+YSXYb(H`aAPUTU}XQU)oNC}7~xvcUVghP)KitDGJv)=gso+Rb!X4j zmZxpHY&!?O`2DI=9}UmIO-TGS{6;iSkZMjQM;D7Ii_PSO>4wD1-Gxd+218Djn|>zG zq1C8ysBMZv`StSEk-Bmh=J=EjHOI;dVP662{8xy-ma~9*?jDm3Vw|!%ve#u!Dc&86 zetWR8O&DWy$@R6l!piEjWx)&M#e|Jjl?r85Vm76%Av;vjZmbIsRIm$|#F^!cUkDHg zmq1?*!`iyz*oWY2-Yz`SZvBfc6iSLcC*>B8<6E1?%;M4a>y(NSN?=I9mp_$>Z5aqaH{U|vnB?gK zJJY=&j3b$YU>NRdT%hSHMbhuyk6N6yR zuUEN-n3GdAZM3aBQzpU73ocl~d)xeM1lO$xjinTImuF{!-#1Ud_p+UAQNfHZ) zT<&5?Uus^mVct~AyhmLlMPuYYNYbfiR=%RVukfyWUaTHvz@@Y;R2xi+9kfhuYu@I{ zZL7qvNwi}DK_Wn4(;2AD1a!ZT5`(&gXI;_Zpzr>}kc z2`t-xoty!p0@3ZjO)1K~oqCkkeUjk6PaL#Sr4fzc_z*;UpzdES-0&j0^$G5e0?e}E zo(D)DQ4S#Jk1xt5(C)IdrpiWd?~Q1t>CQ%@dXnY&S8{wMCFd@aPR8HS@Q3h zZx;ZH;qYwff7p2V>HX9z!fRkk{H_xMy?2c5;O?dRczZ;MtsdrNHWD^oq(-=B)B348 zL$UvIKPD|01YImban;`=AoRaNaBy}`pokF_i4|42=D9dIA~=rT=c%o(ZI>_bLvX1W zd6?5Um+mld#;Fs6_L=c4XKlXY;`h+|FoXR==7`V#?;)lVgU$A&bM-cAupHVE{?r*- z8<`OeGIR)d=#Bd$>hI459W8Lhy&EgMXhe$G(7=q9ZL^Rcg5=i6;m6dlURn3!P0I#x zAXzM<_KT@^pA`W~*||^)wT7&|4L)1a=|pujlv#1{7vUnPV{_|6iM6@$dZ)THrl5SS zj`$0#EP-hZ7vGRo(I$v_At5O?a6gW0fNEo~_E(-i_mFdK`vQw|Tuny)Ep_5K{u+xu zyj&fPC`31Tc^PT%0L~yZw24TEJo;VVDBr{*l2@)GDhsw z@fkED<>(a!-!@GfBHABTz2(k^%KdnOQL3Q8g+!i!-}sx%?s?t_KIS~jenLR(R_RMz zAa}+V4>%%RzonL~-qeLKZz&sbt@vwTqi%X`*M)rTECt02MHOE`#v?2X${JMdMt22? zr6XuZ(@$lI{3%VYfxKNNqC)rqxxys~(jqs07FC&Z_RcuYvV)jldrO%SOoR}r-6eGS z`}>M}ZM}R?C&+m)p^(Hi%>lPtHatQ}SDPh^+M-X&))La1fJna^i4pGH1bjf0HHj5K z{917oVJvqWE=Sm5lSV7$_MLkWer}1fPAK*HqQSeqEmNMB^@q8%F}}q%rUk#CLG~fK z**RZ-PEs_b;`|93pJ;nw50~(mX8-K9FzzT#{rDG#ARj0lVSf(Ec0D|!wQL^(duT+j zh#pySRz;k!x|m4H*i28w?w>53qrx=2b@y5~`OSL}>s`u~hupp)f2l-2LeUg;a?#^k z9EQi(U?n0+9aG#kM(hWKl-%-j$(9>6rZvR~qz{Op96>0E>rQo719!Daz;-{1)}Th!LHL5A2jeLE0uY%iiugXn|ujO>av?`jgKa z>dV$1zA@h!L>q@(-wE?yFI;u#XBS97|AP_8T#L8CA>AVMyL6J1zy1k<&sGaDr3cZ0sl@{_i~F>5iHg2Ud|JZe7iwPSvJw{}}J&Z|tL3(%lz98ZU#d zMBo>BOz=PtcME5?^7@7xyUKz#V&bVr>|uKtA<2__PQr@o#$b~pJmw-QS{Cz#RHoa) z_)>ILamYmj_Mh{du+0{i&so&Crk6P(nH8wPB`{Q@ zU8gTP#zF5Y^51Zkbn=wHbYx(w9VKcIAfZmL9-9H%Hg{@xkxUVQ}n zP=+o<`@4tPeIxc6AaXi^7S~X?62m4n={*tJleB#u!8!gS>zB(A<;NB;Y9*MVN2E5( zZ|wH*V)*J~T33?Gt$spWx(*AgInh&vV zwpToYk=03;kq{Vvi=k5qa5aSsrkW3tnj=PwN`?+`QOAXvL>c_m}B7ga

xnCkxhd=`W3i9!8<7z~z51pTUmQOmTNQGz)tA4VsfyT23N!Pt-S z3yCJw1{HA1mX<(D{mBY(^b(*m?lOv2psNwF7^cKJZ9? z1IjKak7=Nj z9SOxcp^kzMP349$ur5}j=FFz_E=8tOaSAai^=I8 zpCzRCW*17jJIOMStz*HN6>M;c662Y_1Ba=~V^iHnr;00j3q!>{3hN`li&JSgbBB0C z#fT31DuAe%#g=TqAvozg(LT00OShK={I$G}0Rl_5JnV%(9)1YTWu*Q;{HatmC*ry2 zAop$%-3ezlC^5_A1)^sa~*+7)9K=-J;UeqcF7Vd4edCJhxtFmH$29Gtg84o8$x z0#|pwAJTN`KEM+guP#SoMTmjDZBv6}M`nmpTT064T(AD5qIu*Z9T){q06zEFD7sw2 zrnxXTXcZZ3F4%WfRMBeH>`HaEj>V`cWDc6VsWX3W+`;7-6w4<6I<`#Z8>dv+>HtFQ zLSRH=*B5>>qZ_Q~%kkPCm)!3Wk3;OiMN4!^ECQbo&+U{CB; zIBXA}h(l>2aPWAYpm58#(7}eG-_DcL_2Mho(g<~iM)>wl_7XW!F6h>bKb!oio7^b_ zuQNm@2&aP4RdHJJM2FLT&htVq$OHxQS<-S(eET zsuu^(p1d%^4XA(^qoh>#W^+a4^qu#5iq&jJtA1@knK8*RceWyB!kP%#yR9VhKAJh> zf$-NcSI8!c>|X~_W@kcUTnetK9z9O6l_>LCv2XP$8Hrk>Q;B^=+TFdvsBHU zF#jo%ao8+v#%qr~QB_CLPomov(te86wyJ|WN=-IS_W0#y*?I6uIldyw{6lUgb}N*o z>bYg}%{xY4CBd>37A=1fx#(#siEKre9&4AV8wdh_;uOS6BA?zR0=OoF`pc~{F~2NJ z($VDM-rlAtCIARONu)fm^oAv&dZ;D~!d$t0yBJb8fnY=PmWxV}=1CxTnt{30Xb~0K zpN#2~IWR3=cA_g&5P2{}&~^BXKakdY z!t?QdW96PqvuzqWoijf08Xm#NhUu>GC`ITHw2j~O&W=+sNix`k5>1&LY)3c699`8; zm`q7d;;Z9ZFY&b=kmqOYif{^qk}RB6*t3Oq?m#4R6sF#2Q&HCmxjMH9h4)`3BaPK|ubTeGurUvEpVw#P(*$PHQQ~lW5-cwwdqfG3?0|*pt;?Lh{ zh@Pp3Ax2i?_!hu3jPm;4IWYd5ZE`cbLi0e>Lvz_|_wKh#pX_UUdqX|+!dM)NY!8)@ z>6e0!0I_7h8SX=V+AY~|;Bc7DKj@D^pK@>@jIQ0()mUsuc$pbHXAC|?2dAdAn8|s+ zU%7~s>vL0EqT;kH@cJbEC#F>zZFSf>rpJ3FvxK3L9m0rdVtg5|FW$sPCPYiR*PA7f zNkisaqo_!cY8U=QX1F~msm@=>(cSjh76`BSIo#tdQCEgSS6l?5w;Oh(Hli^jrt&?M z*>7KE)?gK_b+{Tnu%>4wXMUJU;&k915I*89xLgFW*~|uI3aM;<1t9x!_cG_la>e$C zIh*2i&|cH7f4muCQv|Sb(=14_ote;cNSivxgU#ZPI&YP%IE(w2`#t0f`ZrTjsA7b# zawao<0aO$>q-Po0OiOle%6Kqb$pfkO`TxEp|At*4y^WSa)5b{_H$2BZm}T79%|!I3 z17sn|7gjnq{|#k9&_7EYt)s99!%7(O8x{~1;lq5r!F!qfIUS?UpqbPyhD0)hx)qd_A~*UJg@O;@z34DFA4#; z!!VLFyjZ@+uQScyPL2SXIr!el0uSd%s+Nw}e?mYM@m61Mh==Unl66 zJPFK(ZEHQF#;vA@U%wKBBdf?=**13SN;Kh|!0+C$0&K%L07Q8i2dd%#`kfmY^EDAn z8m`&tb6?Mbvn^1W6!eC&0n_jhY)1O z!n5e;AlleUJz85Ox_*Z_L<~|5U@uXT_8=FVC{Xk&uFx{&m z+fCeLz&Abuna|lMbprj~yAYuh51{9qS2!E`G2X<@Otw+{JU1ry0T%O~$(B#OWkmTO zv!`HUpSOY0pV`;bdCxVjc{v97IN5)xOHO&%0g8bt^*Zpymj>V6RI?9I@Cu`DxG|72 z*RVaLbw7l_N}Vf4%q|CQR?!DmlJgzqmPcE+T7 zN^HRHCCdJ~KtBC8#2K#LHPq0c_8W;o4Y2Ip^lzDdOmwxJC-M+z4Cjbdt+39tm4c zI#q@sdAVj_YM32wFa8=tBzqKK3c^rDB@U#@h)V$LZ95DfzOg%2p9~+~%9s8vz~7E- z<3LD?*|d(2k^U*Q`AmVPHB+lZ$rNb_P5K@94?`GZ2(?Aplq8oT~ut7&oT$HZ&&WP@~9$+ItGD7=b{ zmuNY&?=GLw%Y?nlId{|gaK-VYZ%{*244I(Wn||!)IqbBV8)X8?(Nys!SeQTE&lZ$4 zGKE*E;9%;iX%@=49Ir{b$qtTQ9ziv_iJ;uAxW)04uwY>|YTcn;{|lb>_SPs7Bs6BA zo!(G>s=QF~vs?aW$3J*Ix}<#<>{DS`mm1{~f8m7gRA01wWdC`#^pl3egWsc{H}s0IG(e&ziJ`rX4@Mhne)wYKIzf{gsF~z z5rv*(Z)cqEM#7HoMsb=S_H_cIh#KFg%G?^7c?6}DmoB@-N--D1Hy;#4+%w2mr_=3D zf6W|TiWv&~LUbe5KWh*M{h%#w+6zH{60PhziwvLKi0k9^TtL(rou*R(&Mf4UBI@wX zLs1~ROYPD>MbS}eG(^Tu@WeI!*(nrNs4&Q2kxs%gXio#zjV#*wT}ag}j1PNiLU+2C zPqTcDMEvX0)KUSkh*$;Ekf&cuC$|EtKh;QF<|^l@^5_*`(%)>LElzOuBja4Kq|U_Y z^lw$t2FkeXEP0bQ)hwD2cnQ30?HpIbJNFV`vQqdNl8Mc!cR?JtZ=z74k`dD=bF$^& zIn%otyFBvJNrS#Z<8wL(b{7&N-AqLwKktG5pdzP+-L28tTNWlIrOcSUa6OXSthUCr zp--WE_%PKtj;>%*Wg2%zwE3OGu*RZ%!jJTI`$-k1g|b9 z{b_5X3r`rE_00V6jL-wT=KGPIkLIZ{>+PQvakIf^em|PdqX2>1xXvI5(?8M z@gz)ZWL-3qz|DY$4_G3VIMCHUUBnSLh`*&9e5P*K$`M7Wi!;UNzIfmhQ!-bYtw{PK zKA=Z-e73wwnt|gD#0XUm2w5@luO!vl&c^IrvHvu2KxN^dxXqip*r9mOWPqc|{3a@g z+-k^X0%1hC=$;jGpE&=fVy3DAiL~D$gdvx$OF3bP(5ynh0X!g z>M`?EBS(OZ=&``={t867A!>mzlDDbm6}yAGMOXA}PWTU2VdJl2CEv z26RzgbHs$4-sV>`#sfrE847{cZDX$s^-`XZy#3gevYDx%Kn?u2wWQjGAO6C_4gLHVApoYDbDD zL3N)=)*qD0Weid)jJtGDmCT%=vwxONYa!oV*K2zBfb4KFDHXx|!m?7~d*4*nU+| z>a+%sG|b#PDcEn?2_8k3B;_3waejy_z1n1MG2IXjr%XKe+|(X$)V%&{Z7mAB6RMh0 z-dH3`u%*^{3SQ{T<#^vf`stA=B93%`ZN~K4au8BD1I=tKfndpKxZi$R*Wk;gf|9&c zByv`4X^mKSk}A}cBPh4o{N?+s8Q?kR;8sR1#Loo7*qwI(>1-vxL53kH?X|c7SqZ@2 z_gYJIHts}2Ciu)cC^!=sel0hmKQN9510(~brfYxEC{c8%{x z4;hTf;&54LCro--GC&?ip~0e~;{|Vb%`cCF5$T!$TtE6k zCfv)fCOr~jrW6MIH{K#)9md=I- zY!8S(TkMl*EJ=g%atH7m+5EtjGckWI4(MdERj-a{-8Rqe$}#xWdrU734MSS3J8;@-esK)~Sk3A3Zw?Lze8Oi|K948OU?6Cn;fk`z!1GHLNiQW- z=d?2l7Bm5}S?Sy+iSb$JlRiOwDHi#j6^CRq7al)_epl!aYpe(E<-kftdlZZQqWnr5 z%9$Y&#t4w$MbnFv=+@5PR4r$+#bb#o+#FTtekp1Ie>xcTCc+oaYT`#9epf}~D6@xM z?P|X!c3FJ;6sP~5)vQFBNawE3K7)zrYn?rZg+IDj?D!Kwpg9v4N#<`fRF`qIbPEuU zT-sQL#YQ2)h1R)ta~*ZJJwZtX$-f$x^Js|gy8 zw@WGLoNgBHcVqR45pds&QL$SaiI|9ru;1iy#F6Czy9^7%Lnptd(z#g0c!2D6>IEPvTtQ_(*>%Du)VMT%EHV zx1hzS@k2CH+cklw=nJ;6kY$NK*A_6}4;=SYKEKZ}Yn8~x&oZ~cEk#u_PPa{H``l;D z4nan2iNbD7PQ(gE1?{tabBgCQSS2CLn8cz)tFTBY0Tj!oTO{u`4$I_+Fjvt`WUvP8{xZJ^%)n-XOr}}J1WcsynIs_WYAc#}>|j2KgQkC%Q`VB3rSUt*ZE(Ec zA7%1o8jbTijxZ0WGR8AT)Ucwa;JbH-xm&`Od7bD}^X|r?JB<4HD6TF|iGZrOafV{; zhZGGyoj==ev=_&&ARm3=hA^7)8@IUl8!v7MIn{3sBR7T#PowKD$1N^3Eyt5`hpld4 zY`DOah;UqFMLL_bH*b2F6Qn{%kE=A`y*aygen4;=QGWJ$gjM$?uGJ>tKwCeSXbqP} z5lhZOO3<6075Rfx&C*(=sW3|fX>$J_PF z{?PeWu2o7|KSm#}0BY9Qx*HcUEU4df@x$KI12_3oERDUO)@8GjRi+Y4%AdiTIL$k#Lk!woh*Hy3@Mm*?bi!!8{}q)$O|61lKl$ynx7z_BMCK@+kI=d21Zl4zebl_Z=wL_lb{QZQwB+YxDhf?H$ zx=zgpCOF_KIn9(nqx7#4B~2F*O2BWc)M9G1Gj_pBAq1aL#={8P6Nay`B)cFE3|Bt2 zj3}_G->$=|Uo@kOeUJY_^Vv2^OX>{$P??P(<1aG%M!T*gqSQ$AU9@kDV}%;)7mn%^ zsMJGWzHz7|tslXMuf#~{b0L(d7N(SX58F%f(yC_YU7K==xsuoL0C}*Q08Zu=7kwkG z$%{QyfnPFn>GNH2caK*TTB_xiHmzpzH!_i0%T-xKJ z-IYQ-L9Ap+8B9T581F;0O}8ulEP%ffzA46OMmtVL5XS9d0-Uv)(Cu3VONqK|x_@`J zwRY)b!PZ+Qt@s9g-F&*Zjc?hpc6Ek+n;_IyK3b;OOcrSQv1MOxd)0NDY=9Jq`rDdc z0ZGEuPatc-3X*~X+rM!+#Ke=d$Enbo(As)S&V1~34U@wzJGm7I&DF^#JK1-5-VUzTA}PFo zmB_RCD+w&y=M~CpGA0Wy6Hx#oMBjTo>xnKoTAO&%4FptssM1>R|2D1*M^yvu;hvr- z=pPfPJv0zCJ}NSH%1zy*BP?J8a(f7(@t10(-f~*$4hgUN*&#t(%bAJ<8~xpnURDfApT?{Y12oyV1iUle`QUq4(3(wau(*tp%#FYjmEtQkFtD2*89 zmFTvk*OX=Q2ZwE&eoUF%$ryQtK1x1N67r5ZeU{mdCYpL#xTahD@}SX@vJPk z?T185?-%SdGCu+CZ@1}l>`pa-s=p>%q*{rvq3?1fd;fx4X8W%(Gz&E08;~a|ubPEL zG$UEl2ngH2L=Ru$=r)7{pInyeOm>1oo^)X+ zLae=0T%W^bD>HSqsa%q5v@8&w-o_>T98_!CdZPdv`h)PxbFRa6!|{6yBi94aKH$J5 zvuQ8F$0!(033C1n6{?$mmM7{vu~}`d&hzw#BMp&Q-y8p3sX5Dg2!3V?#4vK< zyi@kStx1{ePsGOyIz=my=_cmIaG)MC65v>;59KRWd;E5rrA_J;xyjKGCQf?YfL|!x zceXojcwICUSjV-fAH@uYk-ZEsEG!uY>&30*#SuG zJ*0oGmvX#=HB}Q@T|kktOTzBCr_acPDn)`>u!Y6`9>c{

- + setMenuIndex(0)}>Account setMenuIndex(1)}>Record setMenuIndex(2)}>REST API @@ -74,6 +75,12 @@ function App() { } + { + menuIndex === 4 && + <> + + + } diff --git a/website/src/db/index.js b/website/src/db/index.js new file mode 100644 index 000000000..bacd5249e --- /dev/null +++ b/website/src/db/index.js @@ -0,0 +1,124 @@ +import Dexie from 'dexie'; + +var db = new Dexie("AleoParameters"); +var PARAMETERS_TABLE = 'parameters'; +db.version(1).stores({ + [PARAMETERS_TABLE]: "name" +}); + +const FILES = [ + // { + // name: 'MintProver', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/mint.prover.11fa6f2' + // }, + // { + // name: 'MintVerifier', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/mint.verifier.e1ae0c8' + // }, + { + name: 'TransferProver', + url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/transfer.prover.95214f1' + }, + { + name: 'TransferVerifier', + url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/transfer.verifier.78aa4e5' + }, + // { + // name: 'JoinProver', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/join.prover.369fac2' + // }, + // { + // name: 'JoinVerifier', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/join.verifier.728e514' + // }, + // { + // name: 'SplitProver', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/split.prover.8713930' + // }, + // { + // name: 'SplitVerifier', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/split.verifier.b6bb949' + // }, + // { + // name: 'FeeProver', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/fee.prover.0a31a56' + // }, + // { + // name: 'FeeVerifier', + // url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/fee.verifier.2186739' + // }, + { + name: 'InclusionProver', + url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/inclusion.prover.209da1d' + }, + { + name: 'InclusionVerifier', + url: 'https://aleo-public.s3.us-west-2.amazonaws.com/testnet3/inclusion.verifier.3f4d6b7' + } +]; + +export async function getAllSavedFiles() { + return await db.table(PARAMETERS_TABLE).toArray(); +} + +export async function getSavedFile(name) { + let files = await db.table(PARAMETERS_TABLE).filter(file => file.name == name).toArray(); + if (files.length == 0) { + throw new Error(`${name} file not found in IndexedDB`); + } + return files[0]; +} + +async function downloadFile(url) { + let response = await fetch(url); + const reader = response.body.getReader(); + const contentLength = +response.headers.get('Content-Length'); + + let receivedLength = 0; // received that many bytes at the moment + let chunks = []; // array of received binary chunks (comprises the body) + while(true) { + const {done, value} = await reader.read(); + + if (done) { + break; + } + + chunks.push(value); + receivedLength += value.length; + + if (chunks.length % 50 == 0) { + console.log(`Received ${receivedLength} of ${contentLength}`); + } + } + + // Step 4: concatenate chunks into single Uint8Array + let chunksAll = new Uint8Array(receivedLength); // (4.1) + let position = 0; + for(let chunk of chunks) { + chunksAll.set(chunk, position); + position += chunk.length; + } + return chunksAll; +} + +export async function downloadAndStoreFiles() { + const existingFiles = await getAllSavedFiles(); + const fileNames = existingFiles.map(file => file.name); + const existingFileNames = new Set(fileNames); + + for (let i = 0; i < FILES.length; i++) { + const { name, url } = FILES[i]; + console.log(`Fetching ${name} parameter file`); + + if (existingFileNames.has(name)) { + console.log(`${name} already saved...`) + continue; + } + + const bytes = await downloadFile(url); + await db.parameters.put({ + name: name, + bytes: bytes + }); + } +} \ No newline at end of file diff --git a/website/src/tabs/transaction/SendCredits.js b/website/src/tabs/transaction/SendCredits.js new file mode 100644 index 000000000..a639b6bdf --- /dev/null +++ b/website/src/tabs/transaction/SendCredits.js @@ -0,0 +1,214 @@ +import React, {useState, useEffect} from "react"; +import {Card, Divider, Form, Input, Button } from "antd"; +const { TextArea } = Input; +import {useAleoWASM} from "../../aleo-wasm-hook"; +import {downloadAndStoreFiles, getSavedFile} from '../../db'; +import {getStateRoot, inputIdsToStatePathMap} from './getChainState'; + +const worker = new Worker("./worker.js"); + +// Create a Promise-based wrapper around postMessage +function postMessagePromise(worker, message) { + return new Promise((resolve, reject) => { + worker.postMessage(message); + worker.onmessage = event => { + resolve(event.data); + }; + worker.onerror = error => { + reject(error); + }; + }); +} + +export const SendCredits = () => { + // Beacon address + + // AViewKey1e9dHqEbCGmh9wXzirbeoB1GAmfaAdGdW9e49X9oNDBMZ aleo1mc6h9k9g03hfkrh93wm6vlew6q2ehzwalqutzjx6hp5mdcv9rsyq2w3alz + const [privateKey, setPrivateKey] = useState("APrivateKey1zkpDKDJELtg3GN29R2UPihgsucvYSkb7BzEYDRkJtZcwhj8"); + // APrivateKey1zkpCGWDkqECBaj14Bcmn7cVPP6LtWHKcihQ5GESSNHEcGyu AViewKey1fj1WFBBeqQZ5q5ytK9p7SS9G6QDYBmmaND2BfVpUMq1J + const [toAddress, setToAddress] = useState("aleo1nhdttzqjjj68qqjge68m7ugpz6d9dq30qxxngyg2qjr9f8hx4cgs42t7wp"); + const [amount, setAmount] = useState(97); + const [plaintext, setPlaintext] = useState(`{ owner: aleo1mc6h9k9g03hfkrh93wm6vlew6q2ehzwalqutzjx6hp5mdcv9rsyq2w3alz.private, gates: 9973u64.private, _nonce: 1157538218493794217455834413151916695596644156738232294925137030650794330428group.public}`); + + const [stateRoot, setStateRoot] = useState(''); + const [statePaths, setStatePaths] = useState(''); + const [transition, setTransition] = useState(''); + const [inputIds, setInputIds] =useState(''); + + const [transaction, setTransaction] = useState(""); + + const aleo = useAleoWASM(); + + useEffect(() => { + worker.addEventListener("message", ev => { + if (ev.data.type == 'TRANSITION_COMPLETED') { + const data = JSON.parse(ev.data.transition); + setTransition(JSON.stringify(data.transition)); + setInputIds(JSON.stringify(data.input_ids)); + } else if (ev.data.type == 'TRANSACTION_COMPLETED') { + setTransaction(ev.data.transaction); + } + }); + }, []); + + const safeStateUpdate = (update, event) => { + try { update(event.target.value) } + catch (error) { console.error(error)} + } + + const buildTransition = async () => { + try { + // Download files + let startTime = performance.now(); + await downloadAndStoreFiles(); + console.log(`Download Completed: ${performance.now() - startTime} ms`); + startTime = performance.now(); + + // Get transfer prover from IndexedDB + const transferProver = await getSavedFile('TransferProver'); + console.log(transferProver); + console.log(`Fetching Transfer Prover from IndexedDb Completed: ${performance.now() - startTime} ms`); + await postMessagePromise(worker, { + type: 'ALEO_LOAD_TRANSFER_KEY', + transferProverBytes: transferProver.bytes + }); + + // Build transition + await postMessagePromise(worker, { + type: 'ALEO_CREATE_TRANSITION', + privateKey, + amount, + toAddress, + plaintext + }); + } catch (error) { console.error(error) } + } + + const buildTransaction = async () => { + try { + // Update state root + const newStateRoot = await getStateRoot(); + setStateRoot(newStateRoot); + + // Update state paths + const newStatePaths = JSON.stringify(await inputIdsToStatePathMap(inputIds)); + setStatePaths(newStatePaths); + + // Get inclusion prover + let startTime = performance.now(); + const inclusionProver = await getSavedFile('InclusionProver'); + console.log(inclusionProver); + console.log(`Fetching Inclusion Prover from IndexedDb Completed: ${performance.now() - startTime} ms`); + const inclusionProverBytes = inclusionProver.bytes; + await postMessagePromise(worker, { + type: 'ALEO_LOAD_INCLUSION_KEY', + inclusionProverBytes + }); + + // Build transaction + await postMessagePromise(worker, { + type: 'ALEO_CREATE_TRANSACTION', + transition, + inputIds, + stateRoot: newStateRoot, + statePaths: newStatePaths + }); + } catch (error) { console.error(error) } + } + + const verifyTransaction = async () => { + try { + // Get transfer verifier + let startTime = performance.now(); + const transferVerifier = await getSavedFile('TransferVerifier'); + console.log(transferVerifier); + console.log(`Fetching Transfer Verifier from IndexedDb Completed: ${performance.now() - startTime} ms`); + const transferVerifierBytes = transferVerifier.bytes; + + // Get inclusion verifier + startTime = performance.now(); + const inclusionVerifier = await getSavedFile('InclusionVerifier'); + console.log(inclusionVerifier); + console.log(`Fetching Inclusion Verifier from IndexedDb Completed: ${performance.now() - startTime} ms`); + const inclusionVerifierBytes = inclusionVerifier.bytes; + + // Verify Transaction + await postMessagePromise(worker, { + type: 'ALEO_VERIFY_TRANSACTION', + transaction, + transferVerifierBytes, + inclusionVerifierBytes + }); + } catch (error) { console.error(error) } + } + + + const layout = {labelCol: {span: 4}, wrapperCol: {span: 21}}; + + if (aleo !== null) { + return +
+ + safeStateUpdate(setPrivateKey, evt)} + style={{borderRadius: '20px'}}/> + + + safeStateUpdate(setToAddress, evt)} + style={{borderRadius: '20px'}}/> + + + safeStateUpdate(setAmount, evt)} + style={{borderRadius: '20px'}}/> + + +