diff --git a/Cargo.lock b/Cargo.lock index 88b38ba1b9..a519259a7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,7 +70,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9ebd144c81671193ed85aa2db9bb5e183421843e0485de8fffc07e5cf50e18a" dependencies = [ "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "syn 1.0.109", ] @@ -81,7 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f6ff9e4c36858fa2c29e5284b77527b5a7466743976e1ba1f5824e16683545" dependencies = [ "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "syn 1.0.109", ] @@ -211,8 +211,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -227,6 +227,83 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "axum" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +dependencies = [ + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-extra" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "serde_core", + "serde_json", + "tower-layer", + "tower-service", + "tracing", + "typed-json", +] + [[package]] name = "backtrace" version = "0.3.76" @@ -262,9 +339,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82" [[package]] name = "bech32" @@ -357,9 +434,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "byteorder" @@ -390,9 +467,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.49" +version = "1.2.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" dependencies = [ "find-msvc-tools", "shlex", @@ -425,9 +502,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -435,9 +512,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -453,8 +530,8 @@ checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -671,7 +748,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.1.2", + "rustix 1.1.3", "signal-hook", "signal-hook-mio", "winapi", @@ -699,7 +776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -778,15 +855,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] name = "darling" -version = "0.20.11" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -794,27 +871,40 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -843,7 +933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "syn 1.0.109", ] @@ -854,30 +944,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "rustc_version", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -944,8 +1034,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -1025,7 +1115,7 @@ dependencies = [ "ff", "generic-array", "group", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1071,8 +1161,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -1119,7 +1209,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1131,9 +1221,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" [[package]] name = "fixedbitset" @@ -1194,18 +1284,13 @@ dependencies = [ ] [[package]] -name = "futures" -version = "0.3.31" +name = "forwarded-header-value" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "nonempty", + "thiserror 1.0.69", ] [[package]] @@ -1253,13 +1338,18 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-sink", @@ -1308,9 +1398,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -1319,6 +1411,29 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +[[package]] +name = "governor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb" +dependencies = [ + "cfg-if", + "dashmap", + "futures-sink", + "futures-timer", + "futures-util", + "getrandom 0.3.4", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand 0.9.2", + "smallvec", + "spinning_top", + "web-time", +] + [[package]] name = "group" version = "0.13.0" @@ -1326,15 +1441,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -1349,6 +1464,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.5" @@ -1371,6 +1492,30 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.5.0" @@ -1446,6 +1591,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "hyper" version = "1.8.1" @@ -1460,6 +1611,7 @@ dependencies = [ "http", "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "pin-utils", @@ -1660,13 +1812,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", - "rayon", + "rayon 1.11.0", "serde", "serde_core", ] @@ -1695,15 +1847,15 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6778b0196eefee7df739db78758e5cf9b37412268bfa5650bfeed028aed20d9c" +checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" dependencies = [ "darling", "indoc", "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -1714,14 +1866,25 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1748,9 +1911,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" @@ -1837,8 +2000,8 @@ dependencies = [ "itertools 0.13.0", "leo-errors", "leo-span", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "serde_json", "snarkvm", @@ -1860,8 +2023,8 @@ dependencies = [ "leo-passes", "leo-span", "leo-test-framework", - "rand_chacha", - "rayon", + "rand_chacha 0.3.1", + "rayon 0.8.2", "regex", "serde", "serde_json", @@ -1912,8 +2075,8 @@ dependencies = [ "leo-parser", "leo-span", "leo-test-framework", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "ratatui", "regex", "serial_test", @@ -1927,8 +2090,11 @@ name = "leo-lang" version = "3.4.0" dependencies = [ "aleo-std", + "aleo-std-storage", "ansi_term", "anyhow", + "axum", + "axum-extra", "backtrace", "chrono", "clap", @@ -1940,6 +2106,7 @@ dependencies = [ "dotenvy", "dunce", "indexmap", + "is-terminal", "itertools 0.13.0", "leo-ast", "leo-compiler", @@ -1953,10 +2120,11 @@ dependencies = [ "num-format", "once_cell", "parking_lot", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 0.8.2", "regex", + "reqwest", "rpassword", "self_update", "serde", @@ -1967,6 +2135,9 @@ dependencies = [ "snarkvm", "sys-info", "tempfile", + "tokio", + "tower-http", + "tower_governor", "tracing", "tracing-subscriber", "ureq", @@ -2059,21 +2230,21 @@ dependencies = [ name = "leo-test-framework" version = "3.4.0" dependencies = [ - "rayon", + "rayon 0.8.2", "walkdir", ] [[package]] name = "libc" -version = "0.2.178" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", @@ -2149,10 +2320,10 @@ dependencies = [ "fnv", "lazy_static", "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "regex-syntax", "rustc_version", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2175,13 +2346,28 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" dependencies = [ "hashbrown 0.16.1", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "memchr" version = "2.7.6" @@ -2257,6 +2443,12 @@ dependencies = [ "libc", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + [[package]] name = "nom" version = "7.1.3" @@ -2267,6 +2459,18 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2299,8 +2503,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -2405,8 +2609,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -2481,6 +2685,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2511,9 +2735,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "potential_utf" @@ -2547,13 +2771,28 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-xml" version = "0.23.1" @@ -2571,9 +2810,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -2591,8 +2830,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -2602,7 +2851,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -2614,13 +2873,22 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "rand_xorshift" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -2644,6 +2912,24 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rayon" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +dependencies = [ + "rayon-core", +] + [[package]] name = "rayon" version = "1.11.0" @@ -2715,9 +3001,9 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -2830,9 +3116,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", @@ -2843,9 +3129,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", @@ -2858,9 +3144,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "zeroize", ] @@ -2884,9 +3170,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "same-file" @@ -3039,20 +3325,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "indexmap", "itoa", "memchr", - "ryu", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", "serde", "serde_core", ] @@ -3071,11 +3368,12 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" dependencies = [ - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot", @@ -3085,13 +3383,24 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", ] [[package]] @@ -3159,10 +3468,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -3173,7 +3483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3211,13 +3521,12 @@ dependencies = [ [[package]] name = "snarkvm" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2650900efb0df263e678b7f0f423e99277da3c6c62c63062a1639242bb73644" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", "dotenvy", - "rand", + "rand 0.8.5", "serde_json", "snarkvm-algorithms", "snarkvm-circuit", @@ -3232,9 +3541,8 @@ dependencies = [ [[package]] name = "snarkvm-algorithms" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc064d3ad09ca7a22e9659212d4fddf28e4bbc9c96d4aa2288aa17933498117" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", @@ -3246,8 +3554,8 @@ dependencies = [ "indexmap", "itertools 0.14.0", "num-traits", - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "serde", "sha2", "smallvec", @@ -3260,9 +3568,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13621a445caf8ee1958e835e14a0f8974bd0b757ebd4de4fe22b9063e45aad40" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -3275,9 +3582,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-account" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df5d6cb0579ec9e9f473d85ee985cb6cf021d35541262dc770438164f60a328" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-network", "snarkvm-circuit-types", @@ -3286,9 +3592,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-algorithms" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75f80d1dd05e4f5daaee601240c0bec20fafdafa5246cc2c48382940ce08b6d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-types", "snarkvm-console-algorithms", @@ -3297,9 +3602,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-collections" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c70bfd65cf988f1546b5f7b3751b62977a1937ffebad090850a784ebb0a96a" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-types", @@ -3308,9 +3612,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901cc5c67082b0df337ee26f2bfb3b70a2ca51d64e6f200cf11f7a1708bfc1d9" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "indexmap", "itertools 0.14.0", @@ -3327,15 +3630,13 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment-witness" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884964c0c167823e6ee76fc1ae1e647880f07b4a04415371c81de0f0cb5a2e6d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" [[package]] name = "snarkvm-circuit-network" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eab9d33e9eb389d7187a67327ba48482e64ab66924dd934367f4cd4775f6b0" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -3345,9 +3646,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-program" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b137592dd746c7eb4f56f63ecfa9947e62257f9b3b14e335aa8afacd5354217" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -3360,9 +3660,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc98725fbd1fc34be94198f8271f534d1c9049c822a26eaa26432a7edcf6e81a" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -3376,9 +3675,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-address" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550c5271f41cb15316f7a09a5d1faa0411fcef3031a4a23ac51751d9dd9e0b6c" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3390,9 +3688,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-boolean" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bfbc7c607653fd523ef25fccec2fa7084d869468ff49ee58c6069a628786fe" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-console-types-boolean", @@ -3400,9 +3697,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-field" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db5a8888734da5ee5598fe80a70ec251a679fad2c72aaccb039ec8c09836fa" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3411,9 +3707,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-group" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76791b4f4c960b5c8a89c6caa2953315eb70fe8ca0e7734c6354b8206089cce" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3424,9 +3719,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-integers" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3607d81e417bf23dde768575ae16072537e66ed19f8bbd1b96066c66b207f8bb" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3437,9 +3731,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-scalar" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe08c39cb7ce71d947da1fd36c0a677ed9d361edadb42c14f83b9652cf34d6a5" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3449,9 +3742,8 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-string" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf54a2995c69c4e0f770bbd5352204151736f35128190f6361a58b762ae5210" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3462,9 +3754,8 @@ dependencies = [ [[package]] name = "snarkvm-console" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78da46f40feec9078410c2415d36489256b282abf3c1dec85945874115e8803" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -3476,9 +3767,8 @@ dependencies = [ [[package]] name = "snarkvm-console-account" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd345486bab3fbe54a5800a1dfee37e05b0dee06710b4f389fea98645e8f58b6" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "bs58", "snarkvm-console-network", @@ -3488,9 +3778,8 @@ dependencies = [ [[package]] name = "snarkvm-console-algorithms" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ba6389587cd3bd7431ff3280619ae8a5761a46722ae53edcd98172ce027ae3" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "blake2s_simd", "hex", @@ -3504,21 +3793,19 @@ dependencies = [ [[package]] name = "snarkvm-console-collections" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a72b0ca52f5e4059b4159758aac8395155c081953abfddd2c196d43ba9743b5" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", - "rayon", + "rayon 1.11.0", "snarkvm-console-algorithms", "snarkvm-console-types", ] [[package]] name = "snarkvm-console-network" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c92880c09b37d5bdff2ced22e0911cce75e3e425f51783628481d478aa2a80d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", "enum-iterator", @@ -3537,16 +3824,15 @@ dependencies = [ [[package]] name = "snarkvm-console-network-environment" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1aeabebbda7b45b66196cdd9db456d154625b6b3233c477536b82e46024688" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", "bech32", "itertools 0.14.0", "nom", "num-traits", - "rand", + "rand 0.8.5", "serde", "snarkvm-curves", "snarkvm-fields", @@ -3556,9 +3842,8 @@ dependencies = [ [[package]] name = "snarkvm-console-program" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7a0ff48530b8392268dec61f9231b2eb290624d6f58246ada83eaca7bcde99" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "enum-iterator", "enum_index", @@ -3578,9 +3863,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047f4712e7de64699e401c08d80aa11aefbda4bb5a3b97cfe0181b31cb482c8" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-address", @@ -3594,9 +3878,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types-address" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc581d795614ffa23dbf737c44413caf7b25a62845f38649ba00a61be6f124ec" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3606,18 +3889,16 @@ dependencies = [ [[package]] name = "snarkvm-console-types-boolean" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740afa0e3018eb8048f1d2351b92c163214a6d16b73513f9f4fe0de53d8d977c" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", ] [[package]] name = "snarkvm-console-types-field" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d92c4e9dddcdf25942903959d0402cad5baba3d56f0d09d22f4ee95fc24cb5" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3626,9 +3907,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types-group" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10ea02928ed85ea863cac8eb429ba92232d8e0aba7f111473b42665eedcc794f" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3638,9 +3918,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types-integers" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca7cfb62960c945521065a04cabf5b25cb9925027455c4f428d7613afc22a77d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3650,9 +3929,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types-scalar" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "593c61497ce4658e43d0829b6dd7ee57a01fe5069333f36bd14bcfa1cdeef680" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3662,9 +3940,8 @@ dependencies = [ [[package]] name = "snarkvm-console-types-string" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8eb1d2a1275202adb50f1abae4d6afc1059950435f01bb884da435205bff96b" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3674,12 +3951,11 @@ dependencies = [ [[package]] name = "snarkvm-curves" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b8f4f8477fdd9fbab7bde40b5fd104993b6199227cd219af968384a8e8d657" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "rustc_version", "serde", "snarkvm-fields", @@ -3689,16 +3965,15 @@ dependencies = [ [[package]] name = "snarkvm-fields" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78912e74b5de1807326eb175e75331a9f5c195944746c362e9092dda6b54db8d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "itertools 0.14.0", "num-traits", - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "serde", "snarkvm-utilities", "thiserror 2.0.17", @@ -3707,18 +3982,17 @@ dependencies = [ [[package]] name = "snarkvm-ledger" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7316e32fd40e028b214a9c3699a8c662e8202269d8378ab9d73f79388af110ce" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "indexmap", - "lru 0.16.2", + "lru 0.16.3", "parking_lot", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "snarkvm-console", "snarkvm-ledger-authority", "snarkvm-ledger-block", @@ -3735,12 +4009,11 @@ dependencies = [ [[package]] name = "snarkvm-ledger-authority" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a20386597ffd5550e536265c0a24d823db995df8d555ab59d55b335d823cd2" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-subdag", @@ -3748,13 +4021,12 @@ dependencies = [ [[package]] name = "snarkvm-ledger-block" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39d4687d54811d18d6922e167e432c2f78be2fc31ff849098d90b5a08f56a741" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-authority", @@ -3771,12 +4043,11 @@ dependencies = [ [[package]] name = "snarkvm-ledger-committee" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678d6e0bc202ea821638836c36d129df1f4aec86c19681edffbf0d7ce14bb04" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-batch-header", @@ -3784,9 +4055,8 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00182f1ef4f1d804d884784a3de91246fe3f4b53231434b02f15f35b2146638" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-ledger-narwhal-batch-certificate", "snarkvm-ledger-narwhal-batch-header", @@ -3798,12 +4068,11 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-certificate" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a87acbd36d5851fc746550fc190d37ce56660a48be9659bcc4c0de08ba4ea7f" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-batch-header", @@ -3812,12 +4081,11 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-header" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c94988348c23db830c3431528af45a6c876a2bf1142fcd15f42d128a496762b" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-transmission-id", @@ -3825,9 +4093,8 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-data" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c37c79d6a7f934ed19a7f32391ea1c77567991f3a29b1dfe138b4b8ef27b41" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "bytes", "serde_json", @@ -3837,12 +4104,11 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-subdag" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98fe2242ed6a26b4fe3d52888b392b4560e3ec466ea97e7d06d4083068d9113f" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-committee", @@ -3853,9 +4119,8 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5d7f2d5e27d90ff886c9ce773d85283297027da314bf6ae76bcce09fc76dbf" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "bytes", "serde_json", @@ -3867,9 +4132,8 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission-id" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "850f880f898929b3ad24b6e403c6edeec8c35f40040c5f89c1ae2ef539bf0293" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "snarkvm-console", "snarkvm-ledger-puzzle", @@ -3877,19 +4141,18 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94e53be712268f4d0994899fa2d5143606da62e1946265607abe58fa7a6723c" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "bincode", "indexmap", - "lru 0.16.2", + "lru 0.16.3", "parking_lot", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "serde_json", "snarkvm-algorithms", "snarkvm-console", @@ -3897,19 +4160,18 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle-epoch" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c2b866424dba58368d47e85e4529e4dbae68cf346ab1f9b7e2dd08631c5697" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "colored 3.0.0", "indexmap", - "lru 0.16.2", + "lru 0.16.3", "parking_lot", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "snarkvm-circuit", "snarkvm-console", "snarkvm-ledger-puzzle", @@ -3920,9 +4182,8 @@ dependencies = [ [[package]] name = "snarkvm-ledger-query" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b9a6594198d17477adc72a8fbffa495e0c0193dd8fc36e632f787d5b98c694" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "anyhow", "async-trait", @@ -3938,16 +4199,15 @@ dependencies = [ [[package]] name = "snarkvm-ledger-store" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c125333fa216ae69b3f90563a2d06f47511d553bc0f951771709177cfaa1638" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std-storage", "anyhow", "bincode", "indexmap", "parking_lot", - "rayon", + "rayon 1.11.0", "serde", "serde_json", "snarkvm-console", @@ -3959,13 +4219,13 @@ dependencies = [ "snarkvm-synthesizer-program", "snarkvm-synthesizer-snark", "snarkvm-utilities", + "tracing", ] [[package]] name = "snarkvm-parameters" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1f5f415330dbb5c5921ef6d05962b5d18f239c12d4f1a12795a592ecde6038" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", @@ -3976,7 +4236,7 @@ dependencies = [ "lazy_static", "parking_lot", "paste", - "rand", + "rand 0.8.5", "serde_json", "sha2", "snarkvm-curves", @@ -3986,18 +4246,17 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0092bc65216609a180c01e8a03b2a527d6b527e8776ce71785b932f901893e" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "indexmap", "itertools 0.14.0", - "lru 0.16.2", + "lru 0.16.3", "parking_lot", - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "serde_json", "snarkvm-algorithms", "snarkvm-circuit", @@ -4013,22 +4272,22 @@ dependencies = [ "snarkvm-synthesizer-program", "snarkvm-synthesizer-snark", "snarkvm-utilities", + "tokio", "tracing", ] [[package]] name = "snarkvm-synthesizer-process" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28ceadf64062805b4a48b298c206a9f5a4bb12032a9a60465ef1e0a5766cdf77" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "colored 3.0.0", "indexmap", "parking_lot", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "serde_json", "snarkvm-algorithms", "snarkvm-circuit", @@ -4043,16 +4302,15 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-program" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc32136ef3ac69aaeab040e11e4a0bdc8c00dbae778c0d3b65120d179e44eb9" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "enum-iterator", "indexmap", "paste", - "rand", - "rand_chacha", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "serde_json", "snarkvm-circuit", "snarkvm-console", @@ -4063,9 +4321,8 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-snark" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175dbc6a6d7cbf188397b81c545323bed27dab554a40e3a6261988f0b1fdca0a" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "bincode", "serde_json", @@ -4077,18 +4334,18 @@ dependencies = [ [[package]] name = "snarkvm-utilities" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b062dc2351b888db6ea293e2ee294b4069c5b9eda242f8d336f08f2ea95150d" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "aleo-std", "anyhow", "bincode", + "colored 3.0.0", "num-bigint", "num_cpus", - "rand", + "rand 0.8.5", "rand_xorshift", - "rayon", + "rayon 1.11.0", "serde", "serde_json", "smol_str", @@ -4100,13 +4357,12 @@ dependencies = [ [[package]] name = "snarkvm-utilities-derives" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a60e21b9d249446399f4c67bf2ca12e1e10bb2539a1812df3202d235213d5b3" +version = "4.3.0" +source = "git+https://github.com/ProvableHQ/snarkVM.git?rev=7787e6e#7787e6e694ec25758b4b7f4fcae9be87fd5e77fa" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -4119,6 +4375,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -4176,9 +4441,9 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck", "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "rustversion", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4205,18 +4470,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.111" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", - "quote 1.0.42", + "quote 1.0.43", "unicode-ident", ] @@ -4245,8 +4510,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -4282,14 +4547,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -4336,8 +4601,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -4347,8 +4612,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -4427,18 +4692,32 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -4461,9 +4740,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -4485,6 +4764,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -4503,6 +4783,7 @@ dependencies = [ "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -4517,12 +4798,29 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tower_governor" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e6672c7510df74859726427edea641674dad1aeeb30057b87335b1ba23b843" +dependencies = [ + "axum", + "forwarded-header-value", + "governor", + "http", + "pin-project", + "thiserror 2.0.17", + "tower", + "tracing", +] + [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4535,15 +4833,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -4566,10 +4864,14 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -4580,6 +4882,16 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typed-json" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6024a8d0025400b3f6b189366e9aa92012cf9c4fe1cd2620848dd61425c49eed" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "typenum" version = "1.19.0" @@ -4673,9 +4985,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -4791,7 +5103,7 @@ version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ - "quote 1.0.42", + "quote 1.0.43", "wasm-bindgen-macro-support", ] @@ -4803,8 +5115,8 @@ checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -4839,9 +5151,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -4909,8 +5221,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -4920,8 +5232,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -5154,29 +5466,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -5195,8 +5507,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", "synstructure", ] @@ -5211,13 +5523,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -5249,8 +5561,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", - "quote 1.0.42", - "syn 2.0.111", + "quote 1.0.43", + "syn 2.0.114", ] [[package]] @@ -5281,6 +5593,12 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "zmij" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" + [[package]] name = "zopfli" version = "0.8.3" diff --git a/Cargo.toml b/Cargo.toml index 93471530e4..fd36f55a77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ include = [ ] license = "GPL-3.0" edition = "2024" -rust-version = "1.92.0" +rust-version = "1.90.0" [workspace] members = [ @@ -89,18 +89,31 @@ path = "./test-framework" version = "=3.4.0" [workspace.dependencies.aleo-std] -version = "1.0.1" +version = "1.0.3" + +[workspace.dependencies.aleo-std-storage] +version = "1.0.3" default-features = false [workspace.dependencies.anyhow] version = "1.0" +[workspace.dependencies.axum] +version = "0.8.0" + +[workspace.dependencies.axum-extra] +version = "0.10" +features = ["erased-json", "typed-header"] + [workspace.dependencies.base62] version = "2.2.1" [workspace.dependencies.colored] version = "2.0" +[workspace.dependencies.http] +version = "1" + [workspace.dependencies.indexmap] version = "2.6" features = [ "serde" ] @@ -111,6 +124,12 @@ version = "0.13.0" [workspace.dependencies.paste] version = "1.0" +[workspace.dependencies.is-terminal] +version = "0.4" + +[workspace.dependencies.parking_lot] +version = "0.12" + [workspace.dependencies.rand] version = "0.8" default-features = false @@ -120,11 +139,14 @@ version = "0.3.0" default-features = false [workspace.dependencies.rayon] -version = "1.11.0" +version = "0.8" [workspace.dependencies.regex] version = "1.11.1" +[workspace.dependencies.reqwest] +version = "0.12.23" + [workspace.dependencies.self_update] version = "0.41.0" features = [ "archive-zip", "compression-zip-deflate" ] @@ -144,15 +166,30 @@ version = "3.1.1" version = "0.10.9" [workspace.dependencies.snarkvm] -version = "4.4.0" -features = [ "test_consensus_heights" ] +git = "https://github.com/ProvableHQ/snarkVM.git" +rev = "7787e6e" +features = ["dev_skip_checks", "test_consensus_heights", "test_targets"] [workspace.dependencies.tempfile] version = "3.13" +[workspace.dependencies.tokio] +version = "1" +features = ["full"] + +[workspace.dependencies.tower-http] +version = "0.6.0" + +[workspace.dependencies.tower_governor] +version = "0.7" + [workspace.dependencies.tracing] version = "0.1" +[workspace.dependencies.tracing-subscriber] +version = "0.3" +features = ["env-filter", "fmt"] + [workspace.dependencies.ureq] version = "3.0.12" @@ -206,6 +243,15 @@ workspace = true [dependencies.aleo-std] workspace = true +[dependencies.aleo-std-storage] +workspace = true + +[dependencies.axum] +workspace = true + +[dependencies.axum-extra] +workspace = true + [dependencies.backtrace] version = "0.3.74" @@ -240,6 +286,9 @@ version = "1.0.5" [dependencies.indexmap] workspace = true +[dependencies.is-terminal] +version = "0.4" + [dependencies.itertools] workspace = true @@ -264,6 +313,9 @@ workspace = true [dependencies.regex] workspace = true +[dependencies.reqwest] +workspace = true + [dependencies.rpassword] version = "7.4.0" @@ -284,7 +336,7 @@ workspace = true [dependencies.snarkvm] workspace = true -features = [ "circuit", "console" ] +features = ["circuit", "console"] [dependencies.sys-info] version = "0.9.1" @@ -292,12 +344,23 @@ version = "0.9.1" [dependencies.tempfile] version = "3.20.0" +[dependencies.tokio] +workspace = true +features = ["full", "rt-multi-thread", "macros"] + +[dependencies.tower-http] +workspace = true +features = ["cors", "trace"] + +[dependencies.tower_governor] +workspace = true + [dependencies.tracing] workspace = true [dependencies.tracing-subscriber] -version = "0.3.18" -features = [ "fmt" ] +version = "0.3.0" +features = ["env-filter","fmt"] [dependencies.ureq] workspace = true diff --git a/leo/cli/cli.rs b/leo/cli/cli.rs index 6c408cf193..00a2331bde 100644 --- a/leo/cli/cli.rs +++ b/leo/cli/cli.rs @@ -84,6 +84,11 @@ enum Commands { #[clap(flatten)] command: LeoDevnet, }, + #[clap(about = "Run a local devnode")] + Devnode { + #[clap(flatten)] + command: LeoDevnode, + }, #[clap(about = "Query live data from the Aleo network")] Query { #[clap(flatten)] @@ -141,6 +146,7 @@ impl Commands { Commands::Execute { .. } => "execute", Commands::Deploy { .. } => "deploy", Commands::Devnet { .. } => "devnet", + Commands::Devnode { .. } => "devnode", Commands::Query { .. } => "query", Commands::Build { .. } => "build", Commands::Debug { .. } => "debug", @@ -194,7 +200,10 @@ pub fn run_with_args(cli: CLI) -> Result<()> { // Initialize the `.env` file. dotenvy::dotenv().ok(); - if !quiet { + // Skip logger initialization for devnode -- it uses it's own logger. + let is_devnode = matches!(&cli.command, Commands::Devnode { .. }); + + if !quiet && !is_devnode { // Init logger with optional debug flag. logger::init_logger("leo", match cli.debug { false => 1, @@ -231,6 +240,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> { Commands::Clean { command } => command.try_execute(context)?, Commands::Deploy { command } => command_output = Some(JsonOutput::Deploy(command.execute(context)?)), Commands::Devnet { command } => command.try_execute(context)?, + Commands::Devnode { command } => command.try_execute(context)?, Commands::Run { command } => command_output = Some(JsonOutput::Run(command.execute(context)?)), Commands::Test { command } => command_output = Some(JsonOutput::Test(command.execute(context)?)), Commands::Execute { command } => command_output = Some(JsonOutput::Execute(command.execute(context)?)), diff --git a/leo/cli/commands/deploy.rs b/leo/cli/commands/deploy.rs index a883f160af..bca869440d 100644 --- a/leo/cli/commands/deploy.rs +++ b/leo/cli/commands/deploy.rs @@ -24,14 +24,22 @@ use aleo_std::StorageMode; #[cfg(not(feature = "only_testnet"))] use snarkvm::prelude::{CanaryV0, MainnetV0}; use snarkvm::{ - ledger::{query::Query as SnarkVMQuery, store::helpers::memory::BlockMemory}, + circuit::{Aleo, AleoTestnetV0}, + ledger::{ + query::{Query as SnarkVMQuery, QueryTrait}, + store::helpers::memory::BlockMemory, + }, prelude::{ + Certificate, ConsensusVersion, Deployment, + Fee, Program, ProgramID, + ProgramOwner, TestnetV0, VM, + VerifyingKey, deployment_cost, store::{ConsensusStore, helpers::memory::ConsensusMemory}, }, @@ -56,6 +64,8 @@ pub struct LeoDeploy { pub(crate) skip: Vec, #[clap(flatten)] pub(crate) build_options: BuildOptions, + #[clap(long, help = "Use placeholder certificate and verifying keys during deployment.", default_value = "false")] + pub(crate) skip_deploy_certificate: bool, } pub struct Task { @@ -93,25 +103,25 @@ impl Command for LeoDeploy { let network = get_network(&self.env_override.network)?; // Handle each network with the appropriate parameterization. match network { - NetworkName::TestnetV0 => handle_deploy::(&self, context, network, input), + NetworkName::TestnetV0 => handle_deploy::(&self, context, network, input), NetworkName::MainnetV0 => { #[cfg(feature = "only_testnet")] panic!("Mainnet chosen with only_testnet feature"); #[cfg(not(feature = "only_testnet"))] - handle_deploy::(&self, context, network, input) + handle_deploy::(&self, context, network, input) } NetworkName::CanaryV0 => { #[cfg(feature = "only_testnet")] panic!("Canary chosen with only_testnet feature"); #[cfg(not(feature = "only_testnet"))] - handle_deploy::(&self, context, network, input) + handle_deploy::(&self, context, network, input) } } } } // A helper function to handle deployment logic. -fn handle_deploy( +fn handle_deploy>( command: &LeoDeploy, context: Context, network: NetworkName, @@ -288,7 +298,7 @@ fn handle_deploy( let mut transactions = Vec::new(); let mut all_stats = Vec::new(); let mut all_broadcasts = Vec::new(); - for Task { id, program, priority_fee, record, bytecode_size, .. } in local { + for Task { id, program, edition, priority_fee, record, bytecode_size, .. } in local { // If the program is a local dependency that is not skipped, generate a deployment transaction. if !skipped.contains(&id) { // If the program contains an upgrade config, confirm with the user that they want to proceed. @@ -309,35 +319,108 @@ Once it is deployed, it CANNOT be changed. } } println!("📦 Creating deployment transaction for '{}'...\n", id.to_string().bold()); - // Generate the transaction. - let transaction = - vm.deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng) + if command.skip_deploy_certificate { + println!("⚠️ Skipping deployment certificate and verifier key generation as per user request.\n"); + assert!(!program.functions().is_empty(), "Program `{}` has no functions", program.id()); + // Initialize a vector for the placeholder verifying keys and certificates. + let mut verifying_keys = Vec::with_capacity(program.functions().len()); + for function_name in program.functions().keys() { + let (verifying_key, certificate) = { + // Use a placeholder verifying key. + let verifying_key = VerifyingKey::from_str( + "verifier1qygqqqqqqqqqqqyvxgqqqqqqqqq87vsqqqqqqqqqhe7sqqqqqqqqqma4qqqqqqqqqq65yqqqqqqqqqqvqqqqqqqqqqqgtlaj49fmrk2d8slmselaj9tpucgxv6awu6yu4pfcn5xa0yy0tpxpc8wemasjvvxr9248vt3509vpk3u60ejyfd9xtvjmudpp7ljq2csk4yqz70ug3x8xp3xn3ul0yrrw0mvd2g8ju7rts50u3smue03gp99j88f0ky8h6fjlpvh58rmxv53mldmgrxa3fq6spsh8gt5whvsyu2rk4a2wmeyrgvvdf29pwp02srktxnvht3k6ff094usjtllggva2ym75xc4lzuqu9xx8ylfkm3qc7lf7ktk9uu9du5raukh828dzgq26hrarq5ajjl7pz7zk924kekjrp92r6jh9dpp05mxtuffwlmvew84dvnqrkre7lw29mkdzgdxwe7q8z0vnkv2vwwdraekw2va3plu7rkxhtnkuxvce0qkgxcxn5mtg9q2c3vxdf2r7jjse2g68dgvyh85q4mzfnvn07lletrpty3vypus00gfu9m47rzay4mh5w9f03z9zgzgzhkv0mupdqsk8naljqm9tc2qqzhf6yp3mnv2ey89xk7sw9pslzzlkndfd2upzmew4e4vnrkr556kexs9qrykkuhsr260mnrgh7uv0sp2meky0keeukaxgjdsnmy77kl48g3swcvqdjm50ejzr7x04vy7hn7anhd0xeetclxunnl7pd6e52qxdlr3nmutz4zr8f2xqa57a2zkl59a28w842cj4783zpy9hxw03k6vz4a3uu7sm072uqknpxjk8fyq4vxtqd08kd93c2mt40lj9ag35nm4rwcfjayejk57m9qqu83qnkrj3sz90pw808srmf705n2yu6gvqazpvu2mwm8x6mgtlsntxfhr0qas43rqxnccft36z4ygty86390t7vrt08derz8368z8ekn3yywxgp4uq24gm6e58tpp0lcvtpsm3nkwpnmzztx4qvkaf6vk38wg787h8mfpqqqqqqqqqqt49m8x", + )?; + // Use a placeholder certificate. + let certificate = Certificate::from_str( + "certificate1qyqsqqqqqqqqqqxvwszp09v860w62s2l4g6eqf0kzppyax5we36957ywqm2dplzwvvlqg0kwlnmhzfatnax7uaqt7yqqqw0sc4u", + )?; + + (verifying_key, certificate) + }; + verifying_keys.push((*function_name, (verifying_key, certificate))); + } + // Create the deployment. + let mut deployment = + Deployment::new(edition.unwrap_or(0), program.clone(), verifying_keys, None, None).unwrap(); + + // Set the program owner. + deployment.set_program_owner_raw(Some(Address::try_from(&private_key)?)); + + // Compute the checksum of the deployment. + deployment.set_program_checksum_raw(Some(deployment.program().to_checksum())); + + // Compute the deployment ID. + let deployment_id = deployment.to_deployment_id()?; + + // Construct the owner. + let owner = ProgramOwner::new(&private_key, deployment_id, rng)?; + + // Construct the fee authorization. + let (minimum_deployment_cost, _) = + deployment_cost(&vm.process().read(), &deployment, consensus_version)?; + // Authorize the fee. + let fee_authorization = match record { + Some(record) => vm.process().read().authorize_fee_private::( + &private_key, + record, + minimum_deployment_cost, + priority_fee.unwrap_or(0), + deployment_id, + rng, + )?, + None => vm.process().read().authorize_fee_public::( + &private_key, + minimum_deployment_cost, + priority_fee.unwrap_or(0), + deployment_id, + rng, + )?, + }; + + // Get the state root. + let state_root = query.current_state_root()?; + + // Create a fee transition without a proof. + let fee = Fee::from(fee_authorization.transitions().into_iter().next().unwrap().1, state_root, None)?; + + // Create the transaction. + let transaction = Transaction::from_deployment(owner, deployment, fee)?; + // Add the transaction to the transactions vector. + transactions.push((id, transaction)); + } else { + // Generate the transaction. + let transaction = vm + .deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng) .map_err(|e| CliError::custom(format!("Failed to generate deployment transaction: {e}")))?; - // Get the deployment. - let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); - // Compute and print the deployment stats. - let stats = print_deployment_stats( - &vm, - &id.to_string(), - deployment, - priority_fee, - consensus_version, - bytecode_size, - )?; - // Save the transaction and stats. - transactions.push((id, transaction)); - all_stats.push(stats); + // Get the deployment. + let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); + // Compute and print the deployment stats. + let stats = print_deployment_stats( + &vm, + &id.to_string(), + deployment, + priority_fee, + consensus_version, + bytecode_size, + )?; + // Save the transaction. + transactions.push((id, transaction)); + all_stats.push(stats); + } + + if !command.skip_deploy_certificate { + for (program_id, transaction) in transactions.iter() { + // Validate the deployment limits. + let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); + validate_deployment_limits(deployment, program_id, &network)?; + } + } } + // Add the program to the VM. vm.process().write().add_program(&program)?; } - for (program_id, transaction) in transactions.iter() { - // Validate the deployment limits. - let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); - validate_deployment_limits(deployment, program_id, &network)?; - } - // If the `print` option is set, print the deployment transaction to the console. // The transaction is printed in JSON format. if command.action.print { diff --git a/leo/cli/commands/devnode/advance.rs b/leo/cli/commands/devnode/advance.rs new file mode 100644 index 0000000000..fe0971e8b2 --- /dev/null +++ b/leo/cli/commands/devnode/advance.rs @@ -0,0 +1,64 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +use super::*; +use serde_json::json; + +// Advance the Devnode ledger by a specified number of blocks. +#[derive(Parser, Debug)] +pub struct Advance { + #[clap(help = "The number of blocks to advance the ledger by", default_value = "1")] + pub num_blocks: u32, + #[clap(long, help = "devnode REST API server address", default_value = "127.0.0.1:3030")] + pub(crate) socket_addr: String, + #[clap(flatten)] + pub(crate) env_override: EnvOptions, +} + +impl Command for Advance { + type Input = (); + type Output = (); + + fn log_span(&self) -> Span { + tracing::span!(tracing::Level::INFO, "Leo") + } + + fn prelude(&self, _context: Context) -> Result { + Ok(()) + } + + fn apply(self, _context: Context, _: Self::Input) -> Result { + tokio::runtime::Runtime::new().unwrap().block_on(async { handle_advance_devnode(self).await }) + } +} + +async fn handle_advance_devnode(command: Advance) -> Result<::Output> { + tracing::info!("Advancing the Devnode ledger by {} block(s)", command.num_blocks,); + + // Call the REST API to advance the ledger by the specified number of blocks. + let client = reqwest::blocking::Client::new(); + let payload = json!({ + "num_blocks": command.num_blocks, + }); + + let _response = client + .post(format!("http://{}/testnet/block/create", command.socket_addr)) + .header("Content-Type", "application/json") + .json(&payload) + .send(); + + Ok(()) +} diff --git a/leo/cli/commands/devnode/logger.rs b/leo/cli/commands/devnode/logger.rs new file mode 100644 index 0000000000..6ec50626d3 --- /dev/null +++ b/leo/cli/commands/devnode/logger.rs @@ -0,0 +1,60 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +use is_terminal::IsTerminal; +use std::{io, str::FromStr}; +use tracing_subscriber::{EnvFilter, prelude::*}; + +use super::*; + +pub fn initialize_terminal_logger(verbosity: u8) -> Result<()> { + let stdout_filter = parse_log_verbosity(verbosity)?; + + // At high verbosity or when there is a custom log filter we show the target + // of the log event, i.e., the file/module where the log message was created. + let show_target = verbosity > 2; + + // Initialize tracing. + let _ = tracing_subscriber::registry() + .with( + // Add layer using LogWriter for stdout / terminal + tracing_subscriber::fmt::Layer::default() + .with_ansi(io::stdout().is_terminal()) + .with_target(show_target) + .with_filter(stdout_filter), + ) + .try_init(); + + Ok(()) +} + +fn parse_log_verbosity(verbosity: u8) -> Result { + // Note, that this must not be prefixed with `RUST_LOG=`. + let default_log_str = match verbosity { + 0 => "info", + 1 => "debug", + 2.. => "trace", + }; + let filter = EnvFilter::from_str(default_log_str).unwrap(); + + let filter = if verbosity >= 3 { + filter.add_directive("leo_devnode_tcp=trace".parse().unwrap()) + } else { + filter.add_directive("leo_devnode_tcp=off".parse().unwrap()) + }; + + Ok(filter) +} diff --git a/leo/cli/commands/devnode/mod.rs b/leo/cli/commands/devnode/mod.rs new file mode 100644 index 0000000000..032337f5fd --- /dev/null +++ b/leo/cli/commands/devnode/mod.rs @@ -0,0 +1,79 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +mod advance; +pub mod logger; +pub mod rest; +mod start; + +use super::*; +use crate::cli::{ + Command, + EnvOptions, + commands::{Context, Span}, +}; +use clap::Parser; + +#[derive(Parser, Debug)] +pub enum DevnodeCommands { + #[clap(name = "start", about = "Start the Devnode")] + Start { + #[clap(flatten)] + command: start::Start, + }, + #[clap(name = "advance", about = "Advance the ledger by a specified number of blocks")] + Advance { + #[clap(flatten)] + command: advance::Advance, + }, +} + +/// Command for initializing and creating blocks for a local client node. +#[derive(Parser, Debug)] +pub struct LeoDevnode { + #[clap(flatten)] + pub(crate) env_override: EnvOptions, + #[clap(subcommand)] + pub command: DevnodeCommands, +} + +impl Command for LeoDevnode { + type Input = (); + type Output = (); + + fn log_span(&self) -> Span { + tracing::span!(tracing::Level::INFO, "Leo") + } + + fn prelude(&self, _context: Context) -> Result { + Ok(()) + } + + fn apply(self, context: Context, _: Self::Input) -> Result { + handle_devnode(self, context) + } +} + +// A helper function to handle the Devnode command based on the subcommand provided. +fn handle_devnode(devnode_command: LeoDevnode, context: Context) -> Result<::Output> { + match devnode_command.command { + DevnodeCommands::Start { command } => { + tracing::info!("Starting the Devnode server..."); + command.apply(context, ()) + } + DevnodeCommands::Advance { command } => command.apply(context, ()), + } +} diff --git a/leo/cli/commands/devnode/rest/genesis_8d710d7e2_40val_snarkos_dev_network.bin b/leo/cli/commands/devnode/rest/genesis_8d710d7e2_40val_snarkos_dev_network.bin new file mode 100644 index 0000000000..3b2c454d63 Binary files /dev/null and b/leo/cli/commands/devnode/rest/genesis_8d710d7e2_40val_snarkos_dev_network.bin differ diff --git a/leo/cli/commands/devnode/rest/helpers/error.rs b/leo/cli/commands/devnode/rest/helpers/error.rs new file mode 100644 index 0000000000..babaf6f3ad --- /dev/null +++ b/leo/cli/commands/devnode/rest/helpers/error.rs @@ -0,0 +1,159 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . +use anyhow::{Error as AnyhowError, anyhow}; +use tracing::info; + +use axum::{ + extract::rejection::JsonRejection, + http::{StatusCode, header::CONTENT_TYPE}, + response::{IntoResponse, Response}, +}; +use serde::{Deserialize, Serialize}; + +/// An enum of error handlers for the REST API server. +#[derive(Debug)] +pub enum RestError { + /// 400 Bad Request - Invalid input, malformed parameters, validation errors + BadRequest(AnyhowError), + /// 404 Not Found - Resource not found + NotFound(AnyhowError), + /// 422 Unprocessable Entity - Business logic validation errors + UnprocessableEntity(AnyhowError), + /// 429 Too Many Requests - Rate limiting + TooManyRequests(AnyhowError), + // /// 503 Service Unavailable - Temporary service issues (node syncing, feature unavailable) + // ServiceUnavailable(AnyhowError), + /// 500 Internal Server Error - Actual server errors, unexpected failures + InternalServerError(AnyhowError), +} + +/// The serialized REST error sent over the network. +#[derive(Debug, Serialize, Deserialize)] +pub struct SerializedRestError { + pub message: String, + pub error_type: String, + /// Does not include error chain in message if it is empty, and generates an empty error chain if none is given. + #[serde(skip_serializing_if = "Vec::is_empty", default)] + pub chain: Vec, +} + +impl RestError { + /// Create a BadRequest error + pub fn bad_request(inner: anyhow::Error) -> Self { + Self::BadRequest(inner) + } + + /// Create a NotFound error + pub fn not_found(inner: anyhow::Error) -> Self { + Self::NotFound(inner) + } + + /// Create an UnprocessableEntity error + pub fn unprocessable_entity(inner: anyhow::Error) -> Self { + Self::UnprocessableEntity(inner) + } + + /// Create a TooManyRequests error + pub fn too_many_requests(inner: anyhow::Error) -> Self { + Self::TooManyRequests(inner) + } + + /// Create an InternalServerError error + pub fn internal_server_error(inner: anyhow::Error) -> Self { + Self::InternalServerError(inner) + } + + /// Extract the full chain of errors from the `anyhow::Error`. + /// (excludes the top-level error) + fn error_chain(error: &AnyhowError) -> Vec { + let mut chain = vec![]; + let mut source = error.source(); + while let Some(err) = source { + chain.push(err.to_string()); + source = err.source(); + } + chain + } +} + +impl IntoResponse for RestError { + fn into_response(self) -> Response { + let (status, error_type, error) = match self { + RestError::BadRequest(err) => (StatusCode::BAD_REQUEST, "bad_request", err), + RestError::NotFound(err) => (StatusCode::NOT_FOUND, "not_found", err), + RestError::UnprocessableEntity(err) => (StatusCode::UNPROCESSABLE_ENTITY, "unprocessable_entity", err), + RestError::TooManyRequests(err) => (StatusCode::TOO_MANY_REQUESTS, "too_many_requests", err), + RestError::InternalServerError(err) => (StatusCode::INTERNAL_SERVER_ERROR, "internal_server_error", err), + }; + + // Convert to JSON and include the chain of causes (if any). + let json_body = serde_json::to_string(&SerializedRestError { + message: error.to_string(), + error_type: error_type.to_string(), + chain: Self::error_chain(&error), + }) + .unwrap_or_else(|err| format!("Failed to serialize error: {err}")); + + info!("Returning REST error: {json_body}"); + + let mut response = Response::new(json_body.into()); + *response.status_mut() = status; + response.headers_mut().insert(CONTENT_TYPE, "application/json".parse().unwrap()); + response + } +} + +impl From for RestError { + fn from(err: anyhow::Error) -> Self { + // Default to 500 Internal Server Error + Self::InternalServerError(err) + } +} + +impl From for RestError { + fn from(msg: String) -> Self { + // Default to 500 Internal Server Error + Self::InternalServerError(anyhow::anyhow!(msg)) + } +} + +impl From<&str> for RestError { + fn from(msg: &str) -> Self { + // Default to 500 Internal Server Error + Self::InternalServerError(anyhow::anyhow!(msg.to_string())) + } +} + +/// Implement `From` for `RestError` to enable automatic conversion +impl From for RestError { + fn from(rejection: JsonRejection) -> Self { + match rejection { + JsonRejection::JsonDataError(err) => { + RestError::bad_request(anyhow!(err).context("Invalid JSON data in request body")) + } + JsonRejection::JsonSyntaxError(err) => { + RestError::bad_request(anyhow!(err).context("Invalid JSON syntax in request body")) + } + JsonRejection::MissingJsonContentType(_) => { + RestError::bad_request(anyhow!("Content-Type must be `application/json`")) + } + JsonRejection::BytesRejection(err) => { + RestError::bad_request(anyhow!(err).context("Failed to read request body")) + } + _ => RestError::bad_request(anyhow!("Invalid JSON request")), + } + } +} diff --git a/leo/cli/commands/devnode/rest/helpers/mod.rs b/leo/cli/commands/devnode/rest/helpers/mod.rs new file mode 100644 index 0000000000..ad536ce065 --- /dev/null +++ b/leo/cli/commands/devnode/rest/helpers/mod.rs @@ -0,0 +1,21 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +mod error; +pub(crate) use error::*; + +mod path; +pub(crate) use path::Path; diff --git a/leo/cli/commands/devnode/rest/helpers/path.rs b/leo/cli/commands/devnode/rest/helpers/path.rs new file mode 100644 index 0000000000..1ce76c5969 --- /dev/null +++ b/leo/cli/commands/devnode/rest/helpers/path.rs @@ -0,0 +1,106 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +use super::RestError; + +use axum::{ + extract::{FromRequestParts, path::ErrorKind, rejection::PathRejection}, + http::request::Parts, +}; +use serde::de::DeserializeOwned; + +struct PathError { + message: String, + path: String, + cause: anyhow::Error, + location: Option, +} + +/// Convert Path errors into the unified REST error type. +impl From for RestError { + fn from(val: PathError) -> Self { + let err = if let Some(loc) = val.location { + val.cause.context(format!("Invalid argument \"{loc}\" in path \"{}\": {}", val.path, val.message)) + } else { + val.cause.context(format!("Invalid path \"{}\": {}", val.path, val.message)) + }; + + RestError::bad_request(err) + } +} + +/// Custom Path extractor to improve errors in invalid URLs. +/// Adapted from axum's [customize-path-rejection](https://github.com/tokio-rs/axum/blob/main/examples/customize-path-rejection/src/main.rs) +pub struct Path(pub T); + +impl FromRequestParts for Path +where + T: DeserializeOwned + Send, + S: Send + Sync, +{ + type Rejection = RestError; + + async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + match axum::extract::Path::::from_request_parts(parts, state).await { + Ok(value) => Ok(Self(value.0)), + Err(rejection) => { + let err = match rejection { + PathRejection::FailedToDeserializePathParams(inner) => { + let kind = inner.kind(); + + let (message, location) = match &kind { + ErrorKind::WrongNumberOfParameters { .. } => { + ("wrong number of parameters".to_string(), None) + } + ErrorKind::ParseErrorAtKey { key, value, expected_type } => ( + format!("value `{value}` is not of expected type `{expected_type}`"), + Some(key.clone()), + ), + ErrorKind::ParseErrorAtIndex { index, value, expected_type } => ( + format!("value `{value}` at index {index} is not of expected type `{expected_type}`"), + None, + ), + ErrorKind::ParseError { value, expected_type } => { + (format!("value `{value}` is not of expected type `{expected_type}`"), None) + } + ErrorKind::InvalidUtf8InPathParam { key } => { + ("invalid UTF-8 in parameter".to_string(), Some(key.clone())) + } + ErrorKind::Message(msg) => (format!("unknown error: {msg}"), None), + _ => ("unknown error".to_string(), None), + }; + + PathError { message, path: parts.uri.path().to_string(), location, cause: inner.into() } + } + PathRejection::MissingPathParams(error) => PathError { + message: "missing path parameter".to_string(), + path: parts.uri.path().to_string(), + location: None, + cause: error.into(), + }, + _ => PathError { + message: "unknown path error".to_string(), + path: parts.uri.path().to_string(), + location: None, + cause: rejection.into(), + }, + }; + + Err(err.into()) + } + } + } +} diff --git a/leo/cli/commands/devnode/rest/mod.rs b/leo/cli/commands/devnode/rest/mod.rs new file mode 100644 index 0000000000..7ed605a49f --- /dev/null +++ b/leo/cli/commands/devnode/rest/mod.rs @@ -0,0 +1,270 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +#![forbid(unsafe_code)] + +mod helpers; +use helpers::*; + +mod routes; + +use snarkvm::{ + console::{program::ProgramID, types::Field}, + prelude::{Ledger, Network, Transaction, store::ConsensusStorage}, +}; + +use super::*; + +use anyhow::Context; +use axum::{ + body::Body, + extract::{ConnectInfo, DefaultBodyLimit, Query, State}, + http::{Method, Request, StatusCode, header::CONTENT_TYPE}, + middleware, + response::Response, + routing::{get, post}, +}; +use axum_extra::response::ErasedJson; + +use parking_lot::Mutex; +use std::{ + net::SocketAddr, + sync::{Arc, atomic::AtomicUsize}, +}; +use tokio::{net::TcpListener, task::JoinHandle}; +// use tower::util::ServiceExt; +use tower_governor::{GovernorLayer, governor::GovernorConfigBuilder}; +use tower_http::{ + cors::{Any, CorsLayer}, + trace::TraceLayer, +}; +use tracing::{debug, info}; + +/// The API version prefixes. +pub const API_VERSION_V1: &str = "v1"; +pub const API_VERSION_V2: &str = "v2"; + +/// A REST API server for the ledger. +#[derive(Clone)] +pub struct Rest> { + /// The ledger. + ledger: Ledger, + /// A buffer for pending transactions to be added to the next block. + buffer: Arc>>>, + /// The server handles. + handles: Arc>>>, + /// The number of ongoing deploy transaction verifications via REST. + num_verifying_deploys: Arc, + /// The number of ongoing execute transaction verifications via REST. + num_verifying_executions: Arc, + /// Whether manual block creation is enabled. + manual_block_creation: bool, + /// The Private Key used for block creation. + private_key: String, +} + +impl> Rest { + /// Initializes a new instance of the server. + pub async fn start( + rest_ip: SocketAddr, + rest_rps: u32, + ledger: Ledger, + manual_block_creation: bool, + private_key: String, + ) -> Result { + // Initialize the server. + let mut server = Self { + ledger, + buffer: Arc::new(Mutex::new(Vec::new())), + handles: Default::default(), + num_verifying_deploys: Default::default(), + num_verifying_executions: Default::default(), + manual_block_creation, + private_key, + }; + // Spawn the server. + server.spawn_server(rest_ip, rest_rps).await?; + // Return the server. + Ok(server) + } +} + +impl> Rest { + fn build_routes(&self, rest_rps: u32) -> axum::Router { + let cors = CorsLayer::new() + .allow_origin(Any) + .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) + .allow_headers([CONTENT_TYPE]); + + // Prepare the rate limiting setup. + let governor_config = Box::new( + GovernorConfigBuilder::default() + .per_nanosecond((1_000_000_000 / rest_rps) as u64) + .burst_size(rest_rps) + .error_handler(|error| { + // Properly return a 429 Too Many Requests error + let error_message = error.to_string(); + let mut response = Response::new(error_message.clone().into()); + *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + if error_message.contains("Too Many Requests") { + *response.status_mut() = StatusCode::TOO_MANY_REQUESTS; + } + response + }) + .finish() + .expect("Couldn't set up rate limiting for the REST server!"), + ); + + let routes = axum::Router::new() + // Get ../consensus_version + .route("/consensus_version", get(Self::get_consensus_version)) + + // GET ../block/.. + .route("/block/height/latest", get(Self::get_block_height_latest)) + .route("/block/hash/latest", get(Self::get_block_hash_latest)) + .route("/block/latest", get(Self::get_block_latest)) + .route("/block/{height_or_hash}", get(Self::get_block)) + // The path param here is actually only the height, but the name must match the route + // above, otherwise there'll be a conflict at runtime. + .route("/block/{height_or_hash}/header", get(Self::get_block_header)) + .route("/block/{height_or_hash}/transactions", get(Self::get_block_transactions)) + .route("/block/create", post(Self::create_block)) + + // GET and POST ../transaction/.. + .route("/transaction/broadcast", post(Self::transaction_broadcast)) + .route("/transaction/confirmed/{id}", get(Self::get_confirmed_transaction)) + .route("/transaction/unconfirmed/{id}", get(Self::get_unconfirmed_transaction)) + .route("/transaction/{id}", get(Self::get_transaction)) + + // GET ../find/.. + .route("/find/blockHash/{tx_id}", get(Self::find_block_hash)) + .route("/find/blockHeight/{state_root}", get(Self::find_block_height_from_state_root)) + .route("/find/transactionID/deployment/{program_id}", get(Self::find_latest_transaction_id_from_program_id)) + .route("/find/transactionID/deployment/{program_id}/{edition}", get(Self::find_transaction_id_from_program_id_and_edition)) + .route("/find/transactionID/{transition_id}", get(Self::find_transaction_id_from_transition_id)) + .route("/find/transitionID/{input_or_output_id}", get(Self::find_transition_id)) + + // GET ../program/.. + .route("/program/{id}", get(Self::get_program)) + .route("/program/{id}/latest_edition", get(Self::get_latest_program_edition)) + .route("/program/{id}/{edition}", get(Self::get_program_for_edition)) + .route("/program/{id}/mappings", get(Self::get_mapping_names)) + .route("/program/{id}/mapping/{name}/{key}", get(Self::get_mapping_value)) + .route("/program/{id}/mapping/{name}", get(Self::get_mapping_values)) + + // GET misc endpoints. + .route("/blocks", get(Self::get_blocks)) + .route("/height/{hash}", get(Self::get_height)) + .route("/statePath/{commitment}", get(Self::get_state_path_for_commitment)) + .route("/statePaths", get(Self::get_state_paths_for_commitments)) + .route("/stateRoot/latest", get(Self::get_state_root_latest)) + .route("/stateRoot/{height}", get(Self::get_state_root)); + + routes + // Pass in `Rest` to make things convenient. + .with_state(self.clone()) + // Enable tower-http tracing. + .layer(TraceLayer::new_for_http()) + // Custom logging. + .layer(middleware::map_request(log_middleware)) + // Enable CORS. + .layer(cors) + // Cap the request body size at 512KiB. + .layer(DefaultBodyLimit::max(512 * 1024)) + .layer(GovernorLayer { + config: governor_config.into(), + }) + } + + async fn spawn_server(&mut self, rest_ip: SocketAddr, rest_rps: u32) -> Result<()> { + // Log the REST rate limit per IP. + debug!("REST rate limit per IP - {rest_rps} RPS"); + + // Add the v1 API as default and under "/v1". + let default_router = axum::Router::new().nest( + &format!("/{}", N::SHORT_NAME), + self.build_routes(rest_rps).layer(middleware::map_response(v1_error_middleware)), + ); + let v1_router = axum::Router::new().nest( + &format!("/{API_VERSION_V1}/{}", N::SHORT_NAME), + self.build_routes(rest_rps).layer(middleware::map_response(v1_error_middleware)), + ); + + // Add the v2 API under "/v2". + let v2_router = + axum::Router::new().nest(&format!("/{API_VERSION_V2}/{}", N::SHORT_NAME), self.build_routes(rest_rps)); + + // Combine all routes. + let router = default_router.merge(v1_router).merge(v2_router); + + let rest_listener = + TcpListener::bind(rest_ip).await.with_context(|| "Failed to bind TCP port for REST endpoints")?; + + let handle = tokio::spawn(async move { + if let Err(e) = axum::serve(rest_listener, router.into_make_service_with_connect_info::()).await + { + eprintln!("REST server crashed: {e:?}"); + } + }); + + self.handles.lock().push(handle); + Ok(()) + } +} + +/// Creates a log message for every HTTP request. +async fn log_middleware(ConnectInfo(addr): ConnectInfo, request: Request) -> Request { + info!("Received {:?} {:?} from {:?}", request.method(), request.uri(), addr); + request +} + +/// Converts errors to the old style for the v1 API. +/// The error code will always be 500 and the content a simple string. +async fn v1_error_middleware(response: Response) -> Response { + // The status code used by all v1 errors + const V1_STATUS_CODE: StatusCode = StatusCode::INTERNAL_SERVER_ERROR; + + if response.status().is_success() { + return response; + } + + // Returns a opaque error instead of panicking. + let fallback = || { + let mut response = Response::new(Body::from("Failed to convert error")); + *response.status_mut() = V1_STATUS_CODE; + response + }; + + let Ok(bytes) = axum::body::to_bytes(response.into_body(), usize::MAX).await else { + return fallback(); + }; + + // Deserialize REST error so we can convert it to a string. + let Ok(json_err) = serde_json::from_slice::(&bytes) else { + return fallback(); + }; + + let mut message = json_err.message; + for next in json_err.chain.into_iter() { + message = format!("{message} — {next}"); + } + + let mut response = Response::new(Body::from(message)); + + *response.status_mut() = V1_STATUS_CODE; + + response +} diff --git a/leo/cli/commands/devnode/rest/routes.rs b/leo/cli/commands/devnode/rest/routes.rs new file mode 100644 index 0000000000..952b97d819 --- /dev/null +++ b/leo/cli/commands/devnode/rest/routes.rs @@ -0,0 +1,618 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . +use super::*; + +use snarkvm::prelude::{Identifier, LimitedWriter, Plaintext, PrivateKey, Program, ToBytes, Transaction, VM}; + +use axum::{Json, extract::rejection::JsonRejection}; + +use anyhow::{Context, anyhow}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use std::{str::FromStr, sync::atomic::Ordering}; + +use rayon::prelude::*; + +/// Deserialize a CSV string into a vector of strings. +fn de_csv<'de, D>(de: D) -> std::result::Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s = String::deserialize(de)?; + Ok(if s.trim().is_empty() { Vec::new() } else { s.split(',').map(|x| x.trim().to_string()).collect() }) +} + +/// The `get_blocks` query object. +#[derive(Deserialize, Serialize)] +pub(crate) struct BlockRange { + /// The starting block height (inclusive). + start: u32, + /// The ending block height (exclusive). + end: u32, +} + +/// The query object for `get_mapping_value` and `get_mapping_values`. +#[derive(Copy, Clone, Deserialize, Serialize)] +pub(crate) struct Metadata { + metadata: Option, + all: Option, +} + +/// The query object for `transaction_broadcast`. +#[derive(Copy, Clone, Deserialize, Serialize)] +pub(crate) struct CheckTransaction { + check_transaction: Option, +} + +/// The query object for `get_state_paths_for_commitments`. +#[derive(Clone, Deserialize, Serialize)] +pub(crate) struct Commitments { + #[serde(deserialize_with = "de_csv")] + commitments: Vec, +} + +/// The request object for creating a new block. +#[derive(Clone, Deserialize, Serialize)] +pub(crate) struct CreateBlockRequest { + /// number of blocks to create. + pub num_blocks: Option, +} + +impl> Rest { + /// Get //consensus_version + pub(crate) async fn get_consensus_version(State(rest): State) -> Result { + Ok(ErasedJson::pretty(N::CONSENSUS_VERSION(rest.ledger.latest_height())? as u16)) + } + + /// GET //block/height/latest + pub(crate) async fn get_block_height_latest(State(rest): State) -> ErasedJson { + ErasedJson::pretty(rest.ledger.latest_height()) + } + + /// GET //block/hash/latest + pub(crate) async fn get_block_hash_latest(State(rest): State) -> ErasedJson { + ErasedJson::pretty(rest.ledger.latest_hash()) + } + + /// GET //block/latest + pub(crate) async fn get_block_latest(State(rest): State) -> ErasedJson { + ErasedJson::pretty(rest.ledger.latest_block()) + } + + /// GET //block/{height} + /// GET //block/{blockHash} + pub(crate) async fn get_block( + State(rest): State, + Path(height_or_hash): Path, + ) -> Result { + // Manually parse the height or the height of the hash, axum doesn't support different types + // for the same path param. + let block = if let Ok(height) = height_or_hash.parse::() { + rest.ledger.get_block(height).with_context(|| "Failed to get block by height")? + } else if let Ok(hash) = height_or_hash.parse::() { + rest.ledger.get_block_by_hash(&hash).with_context(|| "Failed to get block by hash")? + } else { + return Err(RestError::bad_request(anyhow!( + "invalid input, it is neither a block height nor a block hash" + ))); + }; + + Ok(ErasedJson::pretty(block)) + } + + /// GET //blocks?start={start_height}&end={end_height} + pub(crate) async fn get_blocks( + State(rest): State, + Query(block_range): Query, + ) -> Result { + let start_height = block_range.start; + let end_height = block_range.end; + + const MAX_BLOCK_RANGE: u32 = 50; + + // Ensure the end height is greater than the start height. + if start_height > end_height { + return Err(RestError::bad_request(anyhow!("Invalid block range"))); + } + + // Ensure the block range is bounded. + if end_height - start_height > MAX_BLOCK_RANGE { + return Err(RestError::bad_request(anyhow!( + "Cannot request more than {MAX_BLOCK_RANGE} blocks per call (requested {})", + end_height - start_height + ))); + } + + // Prepare a closure for the blocking work. + let get_json_blocks = move || -> Result { + let blocks = (start_height..end_height) + .into_par_iter() + .map(|height| rest.ledger.get_block(height)) + .collect::, _>>()?; + + Ok(ErasedJson::pretty(blocks)) + }; + + // Fetch the blocks from ledger and serialize to json. + match tokio::task::spawn_blocking(get_json_blocks).await { + Ok(json) => json, + Err(err) => { + let err: anyhow::Error = err.into(); + + Err(RestError::internal_server_error( + err.context(format!("Failed to get blocks '{start_height}..{end_height}'")), + )) + } + } + } + + /// GET //height/{blockHash} + pub(crate) async fn get_height( + State(rest): State, + Path(hash): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_height(&hash)?)) + } + + /// GET //block/{height}/header + pub(crate) async fn get_block_header( + State(rest): State, + Path(height): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_header(height)?)) + } + + /// GET //block/{height}/transactions + pub(crate) async fn get_block_transactions( + State(rest): State, + Path(height): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_transactions(height)?)) + } + + /// GET //transaction/{transactionID} + pub(crate) async fn get_transaction( + State(rest): State, + Path(tx_id): Path, + ) -> Result { + // Ledger returns a generic anyhow::Error, so checking the message is the only way to parse it. + Ok(ErasedJson::pretty(rest.ledger.get_transaction(tx_id).map_err(|err| { + if err.to_string().contains("Missing") { RestError::not_found(err) } else { RestError::from(err) } + })?)) + } + + /// GET //transaction/confirmed/{transactionID} + pub(crate) async fn get_confirmed_transaction( + State(rest): State, + Path(tx_id): Path, + ) -> Result { + // Ledger returns a generic anyhow::Error, so checking the message is the only way to parse it. + Ok(ErasedJson::pretty(rest.ledger.get_confirmed_transaction(tx_id).map_err(|err| { + if err.to_string().contains("Missing") { RestError::not_found(err) } else { RestError::from(err) } + })?)) + } + + /// GET //transaction/unconfirmed/{transactionID} + pub(crate) async fn get_unconfirmed_transaction( + State(rest): State, + Path(tx_id): Path, + ) -> Result { + // Ledger returns a generic anyhow::Error, so checking the message is the only way to parse it. + Ok(ErasedJson::pretty(rest.ledger.get_unconfirmed_transaction(&tx_id).map_err(|err| { + if err.to_string().contains("Missing") { RestError::not_found(err) } else { RestError::from(err) } + })?)) + } + + /// GET //program/{programID} + /// GET //program/{programID}?metadata={true} + pub(crate) async fn get_program( + State(rest): State, + Path(id): Path>, + metadata: Query, + ) -> Result { + // Get the program from the ledger. + let program = rest.ledger.get_program(id).with_context(|| format!("Failed to find program `{id}`"))?; + // Check if metadata is requested and return the program with metadata if so. + if metadata.metadata.unwrap_or(false) { + // Get the edition of the program. + let edition = rest.ledger.get_latest_edition_for_program(&id)?; + return rest.return_program_with_metadata(program, edition); + } + // Return the program without metadata. + Ok(ErasedJson::pretty(program)) + } + + /// GET //program/{programID}/{edition} + /// GET //program/{programID}/{edition}?metadata={true} + pub(crate) async fn get_program_for_edition( + State(rest): State, + Path((id, edition)): Path<(ProgramID, u16)>, + metadata: Query, + ) -> Result { + // Get the program from the ledger. + match rest + .ledger + .try_get_program_for_edition(&id, edition) + .with_context(|| format!("Failed get program `{id}` for edition {edition}"))? + { + Some(program) => { + // Check if metadata is requested and return the program with metadata if so. + if metadata.metadata.unwrap_or(false) { + rest.return_program_with_metadata(program, edition) + } else { + Ok(ErasedJson::pretty(program)) + } + } + None => Err(RestError::not_found(anyhow!("No program `{id}` exists for edition {edition}"))), + } + } + + /// A helper function to return the program and its metadata. + /// This function is used in the `get_program` and `get_program_for_edition` functions. + fn return_program_with_metadata(&self, program: Program, edition: u16) -> Result { + let id = program.id(); + // Get the transaction ID associated with the program and edition. + let tx_id = self.ledger.find_transaction_id_from_program_id_and_edition(id, edition)?; + // Get the optional program owner associated with the program. + // Note: The owner is only available after `ConsensusVersion::V9`. + let program_owner = match &tx_id { + Some(tid) => self + .ledger + .vm() + .block_store() + .transaction_store() + .deployment_store() + .get_deployment(tid)? + .and_then(|deployment| deployment.program_owner()), + None => None, + }; + Ok(ErasedJson::pretty(json!({ + "program": program, + "edition": edition, + "transaction_id": tx_id, + "program_owner": program_owner, + }))) + } + + /// GET //program/{programID}/latest_edition + pub(crate) async fn get_latest_program_edition( + State(rest): State, + Path(id): Path>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_latest_edition_for_program(&id)?)) + } + + /// GET //program/{programID}/mappings + pub(crate) async fn get_mapping_names( + State(rest): State, + Path(id): Path>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.vm().finalize_store().get_mapping_names_confirmed(&id)?)) + } + + /// GET //program/{programID}/mapping/{mappingName}/{mappingKey} + /// GET //program/{programID}/mapping/{mappingName}/{mappingKey}?metadata={true} + pub(crate) async fn get_mapping_value( + State(rest): State, + Path((id, name, key)): Path<(ProgramID, Identifier, Plaintext)>, + metadata: Query, + ) -> Result { + // Retrieve the mapping value. + let mapping_value = rest.ledger.vm().finalize_store().get_value_confirmed(id, name, &key)?; + + // Check if metadata is requested and return the value with metadata if so. + if metadata.metadata.unwrap_or(false) { + return Ok(ErasedJson::pretty(json!({ + "data": mapping_value, + "height": rest.ledger.latest_height(), + }))); + } + + // Return the value without metadata. + Ok(ErasedJson::pretty(mapping_value)) + } + + /// GET //program/{programID}/mapping/{mappingName}?all={true}&metadata={true} + pub(crate) async fn get_mapping_values( + State(rest): State, + Path((id, name)): Path<(ProgramID, Identifier)>, + metadata: Query, + ) -> Result { + // Return an error if the `all` query parameter is not set to `true`. + if metadata.all != Some(true) { + return Err(RestError::bad_request(anyhow!( + "Invalid query parameter. At this time, 'all=true' must be included" + ))); + } + + // Retrieve the latest height. + let height = rest.ledger.latest_height(); + + // Retrieve all the mapping values from the mapping. + match tokio::task::spawn_blocking(move || rest.ledger.vm().finalize_store().get_mapping_confirmed(id, name)) + .await + { + Ok(Ok(mapping_values)) => { + // Check if metadata is requested and return the mapping with metadata if so. + if metadata.metadata.unwrap_or(false) { + return Ok(ErasedJson::pretty(json!({ + "data": mapping_values, + "height": height, + }))); + } + + // Return the full mapping without metadata. + Ok(ErasedJson::pretty(mapping_values)) + } + Ok(Err(err)) => Err(RestError::internal_server_error(err.context("Unable to read mapping"))), + Err(err) => Err(RestError::internal_server_error(anyhow!("Tokio error: {err}"))), + } + } + + /// GET //statePath/{commitment} + pub(crate) async fn get_state_path_for_commitment( + State(rest): State, + Path(commitment): Path>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_state_path_for_commitment(&commitment)?)) + } + + /// GET //statePaths?commitments=cm1,cm2,... + pub(crate) async fn get_state_paths_for_commitments( + State(rest): State, + Query(commitments): Query, + ) -> Result { + // Retrieve the number of commitments. + let num_commitments = commitments.commitments.len(); + // Return an error if no commitments are provided. + if num_commitments == 0 { + return Err(RestError::unprocessable_entity(anyhow!("No commitments provided"))); + } + // Return an error if the number of commitments exceeds the maximum allowed. + if num_commitments > N::MAX_INPUTS { + return Err(RestError::unprocessable_entity(anyhow!( + "Too many commitments provided (max: {}, got: {})", + N::MAX_INPUTS, + num_commitments + ))); + } + + // Deserialize the commitments from the query. + let commitments = commitments + .commitments + .iter() + .map(|s| { + s.parse::>() + .map_err(|err| RestError::unprocessable_entity(err.context(format!("Invalid commitment: {s}")))) + }) + .collect::, _>>()?; + + Ok(ErasedJson::pretty(rest.ledger.get_state_paths_for_commitments(&commitments)?)) + } + + /// GET //stateRoot/latest + pub(crate) async fn get_state_root_latest(State(rest): State) -> ErasedJson { + ErasedJson::pretty(rest.ledger.latest_state_root()) + } + + /// GET //stateRoot/{height} + pub(crate) async fn get_state_root( + State(rest): State, + Path(height): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.get_state_root(height)?)) + } + + /// GET //find/blockHash/{transactionID} + pub(crate) async fn find_block_hash( + State(rest): State, + Path(tx_id): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_block_hash(&tx_id)?)) + } + + /// GET //find/blockHeight/{stateRoot} + pub(crate) async fn find_block_height_from_state_root( + State(rest): State, + Path(state_root): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_block_height_from_state_root(state_root)?)) + } + + /// GET //find/transactionID/deployment/{programID} + pub(crate) async fn find_latest_transaction_id_from_program_id( + State(rest): State, + Path(program_id): Path>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_latest_transaction_id_from_program_id(&program_id)?)) + } + + /// GET //find/transactionID/deployment/{programID}/{edition} + pub(crate) async fn find_transaction_id_from_program_id_and_edition( + State(rest): State, + Path((program_id, edition)): Path<(ProgramID, u16)>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_transaction_id_from_program_id_and_edition(&program_id, edition)?)) + } + + /// GET //find/transactionID/{transitionID} + pub(crate) async fn find_transaction_id_from_transition_id( + State(rest): State, + Path(transition_id): Path, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_transaction_id_from_transition_id(&transition_id)?)) + } + + /// GET //find/transitionID/{inputOrOutputID} + pub(crate) async fn find_transition_id( + State(rest): State, + Path(input_or_output_id): Path>, + ) -> Result { + Ok(ErasedJson::pretty(rest.ledger.find_transition_id(&input_or_output_id)?)) + } + + // /// POST //transaction/broadcast + // /// POST //transaction/broadcast?check_transaction={true} + pub(crate) async fn transaction_broadcast( + State(rest): State, + check_transaction: Query, + json_result: Result>, JsonRejection>, + ) -> Result { + let Json(tx) = match json_result { + Ok(json) => json, + Err(JsonRejection::JsonDataError(err)) => { + // For JsonDataError, return 422 to let transaction validation handle it. + return Err(RestError::unprocessable_entity(anyhow!("Invalid transaction data: {err}"))); + } + Err(other_rejection) => return Err(other_rejection.into()), + }; + let tx_id = tx.id(); + + // If the transaction exceeds the transaction size limit, return an error. + // The buffer is initially roughly sized to hold a `transfer_public`. + // Most transactions will be smaller and this reduces unnecessary allocations. + let buffer = Vec::with_capacity(3000); + if tx.write_le(LimitedWriter::new(buffer, N::MAX_TRANSACTION_SIZE)).is_err() { + return Err(RestError::bad_request(anyhow!("Transaction size exceeds the byte limit"))); + } + + // Determine if we need to check the transaction. + let check_transaction = check_transaction.check_transaction.unwrap_or(true); + + if check_transaction { + // Select counter and limit based on transaction type. + let (counter, limit, err_msg) = if tx.is_execute() { + ( + &rest.num_verifying_executions, + VM::::MAX_PARALLEL_EXECUTE_VERIFICATIONS, + "Too many execution verifications in progress", + ) + } else { + ( + &rest.num_verifying_deploys, + VM::::MAX_PARALLEL_DEPLOY_VERIFICATIONS, + "Too many deploy verifications in progress", + ) + }; + + // Try to acquire a slot. + if counter + .fetch_update( + Ordering::Relaxed, + Ordering::Relaxed, + |val| { + if val < limit { Some(val + 1) } else { None } + }, + ) + .is_err() + { + return Err(RestError::too_many_requests(anyhow!("{err_msg}"))); + } + println!("We've arrived at the transaction check section."); + // Perform the check. + let res = rest + .ledger + .check_transaction_basic(&tx, None, &mut rand::thread_rng()) + .map_err(|err| RestError::unprocessable_entity(err.context("Invalid transaction"))); + + // Release the slot. + counter.fetch_sub(1, Ordering::Relaxed); + // Propagate error if any. + res?; + } + // Create a block with the transaction if the manual block creation feature is not enabled. + if !rest.manual_block_creation { + // Parse the private key. + let private_key = PrivateKey::::from_str(&rest.private_key)?; + + // Clone the ledger for the blocking task + let ledger = rest.ledger.clone(); + // Wrap blocking operations in spawn_blocking + let new_block = tokio::task::spawn_blocking(move || { + ledger.prepare_advance_to_next_beacon_block( + &private_key, + vec![], + vec![], + vec![tx], + &mut rand::thread_rng(), + ) + }) + .await + .map_err(|e| RestError::internal_server_error(anyhow!("Task panicked: {}", e)))??; + + // Advance to the next block. + tokio::task::spawn_blocking(move || rest.ledger.advance_to_next_block(&new_block)) + .await + .map_err(|e| RestError::internal_server_error(anyhow!("Task panicked: {}", e)))??; + return Ok((StatusCode::OK, ErasedJson::pretty(tx_id))); + } + + // Add the transaction to the Rest buffer. + { + let mut buffer = rest.buffer.lock(); + buffer.push(tx); + } + + Ok((StatusCode::OK, ErasedJson::pretty(tx_id))) + } + + /// POST /{network}/create_block + pub(crate) async fn create_block( + State(rest): State, + Json(req): Json, + ) -> Result { + // Determine the number of blocks to create. + let num_blocks = req.num_blocks.unwrap_or(1); + + // Iterate and create the specified number of blocks. + // Return the last created block. + let last_block = tokio::task::spawn_blocking(move || -> Result { + let private_key = PrivateKey::::from_str(&rest.private_key) + .map_err(|e| RestError::bad_request(anyhow!("Invalid private key: {}", e)))?; + + let mut last_block = None; + + // Take all unconfirmed transactions from the buffer. + let mut unconfirmed_txs = Some({ + let mut buffer = rest.buffer.lock(); + buffer.drain(..).collect() + }); + + for _ in 0..num_blocks { + let txs = unconfirmed_txs.take().unwrap_or_default(); + + // Prepare the new block. + let new_block = rest + .ledger + .prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], txs, &mut rand::thread_rng()) + .map_err(|e| RestError::internal_server_error(anyhow!("Failed to prepare block: {}", e)))?; + + // Update the ledger to the new block. + rest.ledger + .advance_to_next_block(&new_block) + .map_err(|e| RestError::internal_server_error(anyhow!("Failed to advance block: {}", e)))?; + + last_block = Some(new_block); + } + + Ok(ErasedJson::pretty(last_block.unwrap())) + }) + .await + .map_err(|e| RestError::internal_server_error(anyhow!("Task panicked: {}", e)))??; + + Ok(last_block) + } +} diff --git a/leo/cli/commands/devnode/start.rs b/leo/cli/commands/devnode/start.rs new file mode 100644 index 0000000000..3101bab062 --- /dev/null +++ b/leo/cli/commands/devnode/start.rs @@ -0,0 +1,129 @@ +// Copyright (C) 2019-2025 Provable Inc. +// This file is part of the Leo library. + +// The Leo 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 Leo 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 Leo library. If not, see . + +use super::{logger::initialize_terminal_logger, *}; +use serde_json::json; +use std::net::SocketAddr; + +use aleo_std_storage::StorageMode; +use snarkvm::{ + ledger::store::helpers::memory::ConsensusMemory, + prelude::{Block, FromBytes, Ledger, TEST_CONSENSUS_VERSION_HEIGHTS, TestnetV0}, +}; + +use crate::cli::commands::devnode::rest::Rest; + +// Command for starting the Devnode server. +#[derive(Parser, Debug)] +pub struct Start { + /// Verbosity level for logging (0-2). + #[clap(short = 'v', long, help = "devnode verbosity (0-2)", default_value = "2")] + pub(crate) verbosity: u8, + /// Address to bind the Devnode REST API server to. + #[clap(long, help = "devnode REST API server address", default_value = "127.0.0.1:3030")] + pub(crate) socket_addr: String, + /// Path to the genesis block file. + #[clap(long, help = "path to genesis block file", default_value = "blank")] + pub(crate) genesis_path: String, + /// Enable manual block creation mode. + #[clap(long, help = "disables automatic block creation after broadcast", default_value = "false")] + pub(crate) manual_block_creation: bool, + /// Environment override options. + #[clap(flatten)] + pub(crate) env_override: EnvOptions, +} + +impl Command for Start { + type Input = (); + type Output = (); + + fn log_span(&self) -> Span { + tracing::span!(tracing::Level::INFO, "Leo") + } + + fn prelude(&self, _context: Context) -> Result { + Ok(()) + } + + fn apply(self, _context: Context, _: Self::Input) -> Result { + let rt = tokio::runtime::Runtime::new().unwrap(); + let _ = rt.block_on(async { start_devnode(self).await }); + Ok(()) + } +} + +// This command initializes a local development node that is pre-populated with test accounts. +pub(crate) async fn start_devnode(command: Start) -> Result<::Output> { + // Initialize the logger. + println!("Starting the Devnode server..."); + initialize_terminal_logger(command.verbosity).expect("Failed to initialize logger"); + // Parse the listener address. + let socket_addr: SocketAddr = command + .socket_addr + .parse() + .map_err(|e| CliError::custom(format!("Failed to parse listener address '{}': {}", command.socket_addr, e)))?; + let rps = 999999999; + // Load the genesis block. + let genesis_block: Block = if command.genesis_path != "blank" { + Block::from_bytes_le(&std::fs::read(&command.genesis_path).map_err(|e| { + CliError::custom(format!("Failed to read genesis block file '{}': {}", command.genesis_path, e)) + })?)? + } else { + // This genesis block is stored in $TMPDIR when running snarkos start --dev 0 --dev-num-validators N + Block::from_bytes_le(include_bytes!("./rest/genesis_8d710d7e2_40val_snarkos_dev_network.bin"))? + }; + // Initialize the storage mode. + let storage_mode = StorageMode::new_test(None); + // Fetch the private key from the command line or an environment variable. + let private_key = match command.env_override.private_key { + Some(key) => key, + None => std::env::var("PRIVATE_KEY") + .map_err(|e| CliError::custom(format!("Failed to load `PRIVATE_KEY` from the environment: {e}")))?, + }; + // Initialize the ledger - use spawn_blocking for the blocking load operation. + let ledger: Ledger> = + tokio::task::spawn_blocking(move || Ledger::load(genesis_block, storage_mode)) + .await + .map_err(|e| CliError::custom(format!("Failed to load ledger: {e}")))??; + // Start the REST API server. + Rest::start(socket_addr, rps, ledger, command.manual_block_creation, private_key) + .await + .expect("Failed to start the REST API server"); + println!("Server running on http://{socket_addr}"); + + // Default setting should fast forward to the block corresponding to the latest consensus version. + // Enabling manual block creation initializes the ledger to the genesis block. + if !command.manual_block_creation { + println!("Advancing the Devnode to the latest consensus version"); + let last_height = TEST_CONSENSUS_VERSION_HEIGHTS.last().unwrap().1; + // Call the REST API to advance the ledger by one block. + let client = reqwest::blocking::Client::new(); + + let payload = json!({ + "num_blocks": last_height, + }); + + let _response = client + .post(format!("http://{}/testnet/block/create", command.socket_addr)) + .header("Content-Type", "application/json") + .json(&payload) + .send(); + } + // Prevent main from exiting. + std::future::pending::<()>().await; + + Ok(()) +} diff --git a/leo/cli/commands/execute.rs b/leo/cli/commands/execute.rs index c93105e11b..5ea093c52a 100644 --- a/leo/cli/commands/execute.rs +++ b/leo/cli/commands/execute.rs @@ -21,7 +21,7 @@ use leo_ast::NetworkName; use leo_package::{Package, ProgramData, fetch_program_from_network}; use aleo_std::StorageMode; -use snarkvm::prelude::{Execution, Itertools, Network, Program, execution_cost}; +use snarkvm::prelude::{Execution, Fee, Itertools, Network, Program, execution_cost}; use clap::Parser; use colored::*; @@ -36,7 +36,7 @@ use snarkvm::{ Identifier, ProgramID, VM, - query::Query as SnarkVMQuery, + query::{Query as SnarkVMQuery, QueryTrait}, store::{ ConsensusStore, helpers::memory::{BlockMemory, ConsensusMemory}, @@ -58,6 +58,8 @@ pub struct LeoExecute { help = "The program inputs e.g. `1u32`, `record1...` (record ciphertext), or `{ owner: ...}` " )] inputs: Vec, + #[clap(long, help = "Skips proving.")] + pub(crate) skip_execute_proof: bool, #[clap(flatten)] pub(crate) fee_options: FeeOptions, #[clap(flatten)] @@ -269,7 +271,7 @@ fn handle_execute( command.inputs.into_iter().map(|string| parse_input(&string, &private_key)).collect::>>()?; // Get the first fee option. - let (_, priority_fee, record) = + let (base_fee, priority_fee, record) = parse_fee_options(&private_key, &command.fee_options, 1)?.into_iter().next().unwrap_or((None, None, None)); // Get the consensus version. @@ -298,6 +300,7 @@ fn handle_execute( &command.action, consensus_version, &check_task_for_warnings(&endpoint, network, &programs, consensus_version), + command.skip_execute_proof, ); // Prompt the user to confirm the plan. @@ -342,17 +345,66 @@ fn handle_execute( .collect::>(); vm.process().write().add_programs_with_editions(&programs_and_editions)?; - // Execute the program and produce a transaction. - println!("\n⚙️ Executing {program_name}/{function_name}..."); - let (transaction, response) = vm.execute_with_response( - &private_key, - (&program_name, &function_name), - inputs.iter(), - record, - priority_fee.unwrap_or(0), - Some(&query), - rng, - )?; + // Generate the execution and fee transitions without proofs if specified. + let (output_name, output, response) = if command.skip_execute_proof { + println!("\n⚙️ Generating transaction WITHOUT a proof for {program_name}/{function_name}..."); + + // Generate the authorization. + let authorization = + vm.process().read().authorize::(&private_key, &program_name, &function_name, inputs.iter(), rng)?; + + // Get the state root. + let state_root = query.current_state_root()?; + + // Create an execution without the proof. + let execution = Execution::from(authorization.transitions().values().cloned(), state_root, None)?; + + // Calculate the cost. + let (cost, _) = execution_cost(&vm.process().read(), &execution, consensus_version)?; + + // Generate the fee authorization. + let id = authorization.to_execution_id()?; + let fee_authorization = match record { + None => { + vm.authorize_fee_public(&private_key, base_fee.unwrap_or(cost), priority_fee.unwrap_or(0), id, rng)? + } + Some(record) => vm.authorize_fee_private( + &private_key, + record, + base_fee.unwrap_or(cost), + priority_fee.unwrap_or(0), + id, + rng, + )?, + }; + + // Create a fee transition without a proof. + let fee = Fee::from(fee_authorization.transitions().into_iter().next().unwrap().1, state_root, None)?; + + // Create the transaction. + let transaction = Transaction::from_execution(execution, Some(fee))?; + + // Evaluate the transaction to get the response. + let response = vm.process().read().evaluate::(authorization)?; + + ("transaction", Box::new(transaction), response) + } else { + println!("\n⚙️ Executing {program_name}/{function_name}..."); + + // Generate the transaction and get the response. + let (transaction, response) = vm.execute_with_response( + &private_key, + (&program_name, &function_name), + inputs.iter(), + record, + priority_fee.unwrap_or(0), + Some(&query), + rng, + )?; + ("transaction", Box::new(transaction), response) + }; + + let transaction = output.clone(); // Compute and print the execution stats. let stats = print_execution_stats::( @@ -367,9 +419,9 @@ fn handle_execute( // If the `print` option is set, print the execution transaction to the console. // The transaction is printed in JSON format. if command.action.print { - let transaction_json = serde_json::to_string_pretty(&transaction) + let transaction_json = serde_json::to_string_pretty(&output) .map_err(|e| CliError::custom(format!("Failed to serialize transaction: {e}")))?; - println!("🖨️ Printing execution for {program_name}\n{transaction_json}"); + println!("🖨️ Printing execution for {output_name}\n{transaction_json}"); } // If the `save` option is set, save the execution transaction to a file in the specified directory. @@ -379,9 +431,9 @@ fn handle_execute( // Create the directory if it doesn't exist. std::fs::create_dir_all(path).map_err(|e| CliError::custom(format!("Failed to create directory: {e}")))?; // Save the transaction to a file. - let file_path = PathBuf::from(path).join(format!("{program_name}.execution.json")); - println!("💾 Saving execution for {program_name} at {}", file_path.display()); - let transaction_json = serde_json::to_string_pretty(&transaction) + let file_path = PathBuf::from(path).join(format!("{output_name}.execution.json")); + println!("💾 Saving execution for {output_name} at {}", file_path.display()); + let transaction_json = serde_json::to_string_pretty(&output) .map_err(|e| CliError::custom(format!("Failed to serialize transaction: {e}")))?; std::fs::write(file_path, transaction_json) .map_err(|e| CliError::custom(format!("Failed to write transaction to file: {e}")))?; @@ -526,6 +578,7 @@ fn print_execution_plan( action: &TransactionAction, consensus_version: ConsensusVersion, warnings: &[String], + skip_execute_proof: bool, ) { println!("\n{}", "🚀 Execution Plan Summary".bold().underline()); println!("{}", "──────────────────────────────────────────────".dimmed()); @@ -550,6 +603,9 @@ fn print_execution_plan( if !is_local { println!(" - Program and its dependencies will be downloaded from the network."); } + if skip_execute_proof { + println!(" - A transaction will be generated, WITHOUT a proof."); + } if action.print { println!(" - Transaction will be printed to the console."); } else { diff --git a/leo/cli/commands/mod.rs b/leo/cli/commands/mod.rs index c7b901bda7..3966b3420a 100644 --- a/leo/cli/commands/mod.rs +++ b/leo/cli/commands/mod.rs @@ -39,6 +39,9 @@ use deploy::{Task, print_deployment_plan, print_deployment_stats}; mod devnet; pub use devnet::LeoDevnet; +mod devnode; +pub use devnode::LeoDevnode; + mod execute; pub use execute::LeoExecute; diff --git a/leo/cli/commands/upgrade.rs b/leo/cli/commands/upgrade.rs index ba3345b216..cebbe406b9 100644 --- a/leo/cli/commands/upgrade.rs +++ b/leo/cli/commands/upgrade.rs @@ -23,11 +23,18 @@ use leo_package::{Package, ProgramData, fetch_program_from_network}; #[cfg(not(feature = "only_testnet"))] use snarkvm::prelude::{CanaryV0, MainnetV0}; use snarkvm::{ - ledger::query::Query as SnarkVMQuery, + circuit::{Aleo, AleoTestnetV0}, + ledger::query::{Query as SnarkVMQuery, QueryTrait}, prelude::{ + Certificate, + Deployment, + Fee, Program, + ProgramOwner, TestnetV0, VM, + VerifyingKey, + deployment_cost, store::{ConsensusStore, helpers::memory::ConsensusMemory}, }, }; @@ -58,6 +65,8 @@ pub struct LeoUpgrade { pub(crate) skip: Vec, #[clap(flatten)] pub(crate) build_options: BuildOptions, + #[clap(long, help = "Skips deployment certificate generation.")] + pub(crate) skip_deploy_certificate: bool, } impl Command for LeoUpgrade { @@ -85,25 +94,25 @@ impl Command for LeoUpgrade { let network = get_network(&self.env_override.network)?; // Handle each network with the appropriate parameterization. match network { - NetworkName::TestnetV0 => handle_upgrade::(&self, context, network, input), + NetworkName::TestnetV0 => handle_upgrade::(&self, context, network, input), NetworkName::MainnetV0 => { #[cfg(feature = "only_testnet")] panic!("Mainnet chosen with only_testnet feature"); #[cfg(not(feature = "only_testnet"))] - handle_upgrade::(&self, context, network, input) + handle_upgrade::(&self, context, network, input) } NetworkName::CanaryV0 => { #[cfg(feature = "only_testnet")] panic!("Canary chosen with only_testnet feature"); #[cfg(not(feature = "only_testnet"))] - handle_upgrade::(&self, context, network, input) + handle_upgrade::(&self, context, network, input) } } } } // A helper function to handle upgrade logic. -fn handle_upgrade( +fn handle_upgrade>( command: &LeoUpgrade, context: Context, network: NetworkName, @@ -311,27 +320,98 @@ fn handle_upgrade( for Task { id, program, priority_fee, record, bytecode_size, .. } in local { // If the program is a local dependency that is not skipped, generate a deployment transaction. if !skipped.contains(&id) { - println!("📦 Creating deployment transaction for '{}'...\n", id.to_string().bold()); - // Generate the transaction. - let transaction = - vm.deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng) + if command.skip_deploy_certificate { + println!("⚠️ Skipping deployment certificate generation as per user request.\n"); + assert!(!program.functions().is_empty(), "Program `{}` has no functions", program.id()); + // Initialize a vector for the placeholder verifying keys and certificates. + let mut verifying_keys = Vec::with_capacity(program.functions().len()); + for function_name in program.functions().keys() { + let (verifying_key, certificate) = { + // Use a placeholder verifying key. + let verifying_key = VerifyingKey::from_str( + "verifier1qygqqqqqqqqqqqyvxgqqqqqqqqq87vsqqqqqqqqqhe7sqqqqqqqqqma4qqqqqqqqqq65yqqqqqqqqqqvqqqqqqqqqqqgtlaj49fmrk2d8slmselaj9tpucgxv6awu6yu4pfcn5xa0yy0tpxpc8wemasjvvxr9248vt3509vpk3u60ejyfd9xtvjmudpp7ljq2csk4yqz70ug3x8xp3xn3ul0yrrw0mvd2g8ju7rts50u3smue03gp99j88f0ky8h6fjlpvh58rmxv53mldmgrxa3fq6spsh8gt5whvsyu2rk4a2wmeyrgvvdf29pwp02srktxnvht3k6ff094usjtllggva2ym75xc4lzuqu9xx8ylfkm3qc7lf7ktk9uu9du5raukh828dzgq26hrarq5ajjl7pz7zk924kekjrp92r6jh9dpp05mxtuffwlmvew84dvnqrkre7lw29mkdzgdxwe7q8z0vnkv2vwwdraekw2va3plu7rkxhtnkuxvce0qkgxcxn5mtg9q2c3vxdf2r7jjse2g68dgvyh85q4mzfnvn07lletrpty3vypus00gfu9m47rzay4mh5w9f03z9zgzgzhkv0mupdqsk8naljqm9tc2qqzhf6yp3mnv2ey89xk7sw9pslzzlkndfd2upzmew4e4vnrkr556kexs9qrykkuhsr260mnrgh7uv0sp2meky0keeukaxgjdsnmy77kl48g3swcvqdjm50ejzr7x04vy7hn7anhd0xeetclxunnl7pd6e52qxdlr3nmutz4zr8f2xqa57a2zkl59a28w842cj4783zpy9hxw03k6vz4a3uu7sm072uqknpxjk8fyq4vxtqd08kd93c2mt40lj9ag35nm4rwcfjayejk57m9qqu83qnkrj3sz90pw808srmf705n2yu6gvqazpvu2mwm8x6mgtlsntxfhr0qas43rqxnccft36z4ygty86390t7vrt08derz8368z8ekn3yywxgp4uq24gm6e58tpp0lcvtpsm3nkwpnmzztx4qvkaf6vk38wg787h8mfpqqqqqqqqqqt49m8x", + )?; + // Use a placeholder certificate. + let certificate = Certificate::from_str( + "certificate1qyqsqqqqqqqqqqxvwszp09v860w62s2l4g6eqf0kzppyax5we36957ywqm2dplzwvvlqg0kwlnmhzfatnax7uaqt7yqqqw0sc4u", + )?; + + (verifying_key, certificate) + }; + verifying_keys.push((*function_name, (verifying_key, certificate))); + } + // Increment the edition. + let edition = *vm.process().read().get_stack(id)?.program_edition() + 1; + println!("edition for deployed program: {}", edition); + let mut deployment = Deployment::new(edition, program.clone(), verifying_keys, None, None).unwrap(); + + // Set the program owner. + deployment.set_program_owner_raw(Some(Address::try_from(&private_key)?)); + + // Compute the checksum of the deployment. + deployment.set_program_checksum_raw(Some(deployment.program().to_checksum())); + + // Compute the deployment ID. + let deployment_id = deployment.to_deployment_id()?; + + // Construct the owner. + let owner = ProgramOwner::new(&private_key, deployment_id, rng)?; + + // Construct the fee authorization. + let (minimum_deployment_cost, _) = + deployment_cost(&vm.process().read(), &deployment, consensus_version)?; + // Authorize the fee. + let fee_authorization = match record { + Some(record) => vm.process().read().authorize_fee_private::( + &private_key, + record, + minimum_deployment_cost, + priority_fee.unwrap_or(0), + deployment_id, + rng, + )?, + None => vm.process().read().authorize_fee_public::( + &private_key, + minimum_deployment_cost, + priority_fee.unwrap_or(0), + deployment_id, + rng, + )?, + }; + + // Get the state root. + let state_root = query.current_state_root()?; + + // Create a fee transition without a proof. + let fee = Fee::from(fee_authorization.transitions().into_iter().next().unwrap().1, state_root, None)?; + + // Create the transaction. + let transaction = Transaction::from_deployment(owner, deployment, fee)?; + // Add the transaction to the transactions vector. + transactions.push((id, transaction)); + } else { + println!("📦 Creating deployment transaction for '{}'...\n", id.to_string().bold()); + // Generate the transaction. + let transaction = vm + .deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng) .map_err(|e| CliError::custom(format!("Failed to generate deployment transaction: {e}")))?; - // Get the deployment. - let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); - // Compute and print the deployment stats. - let stats = print_deployment_stats( - &vm, - &id.to_string(), - deployment, - priority_fee, - consensus_version, - bytecode_size, - )?; - // Validate the deployment limits. - validate_deployment_limits(deployment, &id, &network)?; - // Save the transaction and stats. - transactions.push((id, transaction)); - all_stats.push(stats); + // Get the deployment. + let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); + // Compute and print the deployment stats. + let stats = print_deployment_stats( + &vm, + &id.to_string(), + deployment, + priority_fee, + consensus_version, + bytecode_size, + )?; + // Validate the deployment limits. + validate_deployment_limits(deployment, &id, &network)?; + // Save the transaction and stats. + transactions.push((id, transaction)); + all_stats.push(stats); + } } // Add the program to the VM. vm.process().write().add_program(&program)?; @@ -521,6 +601,7 @@ impl From<&LeoUpgrade> for LeoDeploy { extra: upgrade.extra.clone(), skip: upgrade.skip.clone(), build_options: upgrade.build_options.clone(), + skip_deploy_certificate: upgrade.skip_deploy_certificate, } } }