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 000000000..09489c843 Binary files /dev/null and b/website/public/logo192.png differ diff --git a/website/src/App.js b/website/src/App.js index 9a6a2ffcd..fb11f0c1d 100644 --- a/website/src/App.js +++ b/website/src/App.js @@ -14,17 +14,18 @@ import {GetTransaction} from "./tabs/rest/GetTransaction"; import {NewAccount} from "./tabs/account/NewAccount"; import {SignMessage} from "./tabs/account/SignMessage"; import {VerifyMessage} from "./tabs/account/VerifyMessage"; +import { SendCredits } from './tabs/transaction/SendCredits'; const {Header, Content, Footer} = Layout; function App() { - const [menuIndex, setMenuIndex] = useState(0); + const [menuIndex, setMenuIndex] = useState(4); return (
- + 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'}}/> + + +