diff --git a/Cargo.lock b/Cargo.lock index ee1ee6f240..aa81d7d0ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,9 +38,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -89,7 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9ebd144c81671193ed85aa2db9bb5e183421843e0485de8fffc07e5cf50e18a" dependencies = [ "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "syn 1.0.109", ] @@ -100,7 +100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f6ff9e4c36858fa2c29e5284b77527b5a7466743976e1ba1f5824e16683545" dependencies = [ "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "syn 1.0.109", ] @@ -230,8 +230,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -246,6 +246,83 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "axum" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +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" @@ -356,6 +433,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "bs58" version = "0.5.1" @@ -400,9 +486,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.41" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", "shlex", @@ -435,9 +521,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -445,9 +531,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", @@ -463,8 +549,8 @@ checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -709,7 +795,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", ] @@ -726,11 +812,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3" +checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" dependencies = [ - "dispatch", + "dispatch2", "nix", "windows-sys 0.61.2", ] @@ -752,9 +838,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.83+curl-8.15.0" +version = "0.4.84+curl-8.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5830daf304027db10c82632a464879d46a3f7c4ba17a31592657ad16c719b483" +checksum = "abc4294dc41b882eaff37973c2ec3ae203d0091341ee68fbadd1d06e0c18a73b" dependencies = [ "cc", "libc", @@ -788,8 +874,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -811,9 +897,9 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "strsim", - "syn 2.0.107", + "syn 2.0.109", ] [[package]] @@ -823,8 +909,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", +] + +[[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]] @@ -839,9 +939,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -853,7 +953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "syn 1.0.109", ] @@ -864,8 +964,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -885,8 +985,8 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "convert_case", "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -935,10 +1035,16 @@ dependencies = [ ] [[package]] -name = "dispatch" -version = "0.2.0" +name = "dispatch2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", +] [[package]] name = "displaydoc" @@ -947,15 +1053,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1028,7 +1134,7 @@ dependencies = [ "ff", "generic-array", "group", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1074,8 +1180,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -1122,7 +1228,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", ] @@ -1146,9 +1252,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -1196,6 +1302,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forwarded-header-value" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" +dependencies = [ + "nonempty", + "thiserror 1.0.69", +] + [[package]] name = "futures" version = "0.3.31" @@ -1256,6 +1372,12 @@ 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" @@ -1311,9 +1433,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]] @@ -1322,6 +1446,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" @@ -1329,7 +1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1352,6 +1499,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" @@ -1374,6 +1527,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" @@ -1403,11 +1580,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1450,6 +1627,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.7.0" @@ -1464,6 +1647,7 @@ dependencies = [ "http", "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "pin-utils", @@ -1556,9 +1740,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1569,9 +1753,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1582,11 +1766,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1597,42 +1780,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1675,7 +1854,7 @@ checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown 0.16.0", - "rayon", + "rayon 1.11.0", "serde", "serde_core", ] @@ -1695,9 +1874,12 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "instability" @@ -1708,8 +1890,8 @@ dependencies = [ "darling", "indoc", "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -1720,19 +1902,30 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" 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.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -1760,9 +1953,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1851,8 +2044,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", @@ -1874,8 +2067,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", @@ -1925,8 +2118,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", @@ -1940,8 +2133,11 @@ name = "leo-lang" version = "3.3.1" dependencies = [ "aleo-std", + "aleo-std-storage", "ansi_term", "anyhow", + "axum", + "axum-extra", "backtrace", "chrono", "clap", @@ -1953,6 +2149,7 @@ dependencies = [ "dotenvy", "dunce", "indexmap", + "is-terminal", "itertools 0.13.0", "leo-ast", "leo-compiler", @@ -1966,10 +2163,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", @@ -1980,6 +2178,9 @@ dependencies = [ "snarkvm", "sys-info", "tempfile", + "tokio", + "tower-http", + "tower_governor", "tracing", "tracing-subscriber", "ureq", @@ -2072,7 +2273,7 @@ dependencies = [ name = "leo-test-framework" version = "3.3.1" dependencies = [ - "rayon", + "rayon 0.8.2", "walkdir", ] @@ -2118,15 +2319,15 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" @@ -2162,10 +2363,10 @@ dependencies = [ "fnv", "lazy_static", "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "regex-syntax", "rustc_version", - "syn 2.0.107", + "syn 2.0.109", ] [[package]] @@ -2195,6 +2396,21 @@ dependencies = [ "hashbrown 0.16.0", ] +[[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" @@ -2225,14 +2441,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2270,6 +2486,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" @@ -2280,6 +2502,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" @@ -2312,8 +2546,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -2360,6 +2594,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + [[package]] name = "object" version = "0.37.3" @@ -2377,9 +2626,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" @@ -2403,8 +2652,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -2479,6 +2728,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.42", + "syn 2.0.109", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2515,9 +2784,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -2545,13 +2814,28 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" 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" @@ -2569,9 +2853,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2589,8 +2873,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]] @@ -2600,7 +2894,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]] @@ -2612,13 +2916,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]] @@ -2642,6 +2955,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" @@ -2841,9 +3172,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.33" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "log", "once_cell", @@ -2865,18 +3196,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.7" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -3046,8 +3377,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -3064,6 +3395,17 @@ dependencies = [ "serde_core", ] +[[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", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3097,8 +3439,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", +] + +[[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]] @@ -3155,9 +3508,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -3180,7 +3533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3218,13 +3571,13 @@ dependencies = [ [[package]] name = "snarkvm" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbfddf3f0d6a7578dcd4c6a6ebac28117f07b2a623f72d40aedbbde7ec8e39d8" +checksum = "d2650900efb0df263e678b7f0f423e99277da3c6c62c63062a1639242bb73644" dependencies = [ "anyhow", "dotenvy", - "rand", + "rand 0.8.5", "serde_json", "snarkvm-algorithms", "snarkvm-circuit", @@ -3239,9 +3592,9 @@ dependencies = [ [[package]] name = "snarkvm-algorithms" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0606791227a48fa8982d02032b285a8225d840cd986f1f8343491275cdfbd5a6" +checksum = "dbc064d3ad09ca7a22e9659212d4fddf28e4bbc9c96d4aa2288aa17933498117" dependencies = [ "aleo-std", "anyhow", @@ -3253,8 +3606,8 @@ dependencies = [ "indexmap", "itertools 0.14.0", "num-traits", - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "serde", "sha2", "smallvec", @@ -3267,9 +3620,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61eed7a86ecbdcc67a2f37a5238961eb00c89c24276f96c3e633dc2a5b78ee8" +checksum = "13621a445caf8ee1958e835e14a0f8974bd0b757ebd4de4fe22b9063e45aad40" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -3282,9 +3635,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-account" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091cdb8c0a4ebe850f7f26d109cfb2b12a70d0b41a1895315991b45b1e7785ed" +checksum = "1df5d6cb0579ec9e9f473d85ee985cb6cf021d35541262dc770438164f60a328" dependencies = [ "snarkvm-circuit-network", "snarkvm-circuit-types", @@ -3293,9 +3646,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-algorithms" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3c1233594ef0b17834957d6ec00b9eb84f61755eedcd1899a29edca62d03f0" +checksum = "d75f80d1dd05e4f5daaee601240c0bec20fafdafa5246cc2c48382940ce08b6d" dependencies = [ "snarkvm-circuit-types", "snarkvm-console-algorithms", @@ -3304,9 +3657,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-collections" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a15a5bfc18983765d84f2a00794c607e780403f13766fc2522b182a992921e" +checksum = "d4c70bfd65cf988f1546b5f7b3751b62977a1937ffebad090850a784ebb0a96a" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-types", @@ -3315,9 +3668,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d25962a51d2c0cb0a0ded115bbece828bd5eade125a15f5a6e4e7bfdb4da1ba" +checksum = "901cc5c67082b0df337ee26f2bfb3b70a2ca51d64e6f200cf11f7a1708bfc1d9" dependencies = [ "indexmap", "itertools 0.14.0", @@ -3334,15 +3687,15 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment-witness" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8eb77178b2a23048d1ccd4adb5ef514d87e59c55b2c472ab6ab812124c8a61" +checksum = "884964c0c167823e6ee76fc1ae1e647880f07b4a04415371c81de0f0cb5a2e6d" [[package]] name = "snarkvm-circuit-network" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "253af66ac4cd1b61e6f5b5bea869c36233a4a46708ebb5899573f788561e14c1" +checksum = "38eab9d33e9eb389d7187a67327ba48482e64ab66924dd934367f4cd4775f6b0" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -3352,9 +3705,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-program" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f623587fb20b26dbb574065f417e01d19452b39c792493659f729bcc674a0473" +checksum = "3b137592dd746c7eb4f56f63ecfa9947e62257f9b3b14e335aa8afacd5354217" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -3367,9 +3720,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8f84a58b956c781c425e09fee6634303c7809d554f3ec51eac6bb4cbdcf25c" +checksum = "dc98725fbd1fc34be94198f8271f534d1c9049c822a26eaa26432a7edcf6e81a" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -3383,9 +3736,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-address" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484416709c497ceed0400e16b7cbdc270a8dd4e872b932a1c0fe7fd560f37586" +checksum = "550c5271f41cb15316f7a09a5d1faa0411fcef3031a4a23ac51751d9dd9e0b6c" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3397,9 +3750,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-boolean" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da847758fd0124ea008bc2e45e33e7c826f0edf10c277be4cf78f4a174b20384" +checksum = "30bfbc7c607653fd523ef25fccec2fa7084d869468ff49ee58c6069a628786fe" dependencies = [ "snarkvm-circuit-environment", "snarkvm-console-types-boolean", @@ -3407,9 +3760,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-field" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f818f461ab9766995e1867d455d3467961581aa4c6aca89f1fdc743cbd7e14" +checksum = "e8db5a8888734da5ee5598fe80a70ec251a679fad2c72aaccb039ec8c09836fa" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3418,9 +3771,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-group" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f023f6014a427bf13ae17207327fe26a86fc28a9968c37783b1b6217dd9a36" +checksum = "f76791b4f4c960b5c8a89c6caa2953315eb70fe8ca0e7734c6354b8206089cce" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3431,9 +3784,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-integers" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094099e885bb6388f9493004bf710158316a96257e8b3144a61ccbff79682fee" +checksum = "3607d81e417bf23dde768575ae16072537e66ed19f8bbd1b96066c66b207f8bb" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3444,9 +3797,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-scalar" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fae5ddf15b6ddf0bafbdd84072323ae97ca1037c852fde6adfa4ece2261e10b8" +checksum = "fe08c39cb7ce71d947da1fd36c0a677ed9d361edadb42c14f83b9652cf34d6a5" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3456,9 +3809,9 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-string" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f16a77976a08b0f11aec89d4316567032925925285337635fd289d1aebbe10e" +checksum = "cdf54a2995c69c4e0f770bbd5352204151736f35128190f6361a58b762ae5210" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3469,9 +3822,9 @@ dependencies = [ [[package]] name = "snarkvm-console" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278a25f266a0656fcd86ae2d23edf4ec4514102e4797a36427252f8fbee35fbd" +checksum = "d78da46f40feec9078410c2415d36489256b282abf3c1dec85945874115e8803" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -3483,9 +3836,9 @@ dependencies = [ [[package]] name = "snarkvm-console-account" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a6b7512bbce812edfa89964f0847866195025f1a25be913e70287c02fc9484" +checksum = "fd345486bab3fbe54a5800a1dfee37e05b0dee06710b4f389fea98645e8f58b6" dependencies = [ "bs58", "snarkvm-console-network", @@ -3495,9 +3848,9 @@ dependencies = [ [[package]] name = "snarkvm-console-algorithms" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc29540b10d850dda85ed18d55d1e289616a814784cec164686136ad23c9005" +checksum = "34ba6389587cd3bd7431ff3280619ae8a5761a46722ae53edcd98172ce027ae3" dependencies = [ "blake2s_simd", "hex", @@ -3511,21 +3864,21 @@ dependencies = [ [[package]] name = "snarkvm-console-collections" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0e7c13df3dd2b9b1e548cf686ac5afce750e56c588d141cb5e672c8cbe216b" +checksum = "8a72b0ca52f5e4059b4159758aac8395155c081953abfddd2c196d43ba9743b5" dependencies = [ "aleo-std", - "rayon", + "rayon 1.11.0", "snarkvm-console-algorithms", "snarkvm-console-types", ] [[package]] name = "snarkvm-console-network" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b21a29cfe4f3db2b983e66d17a0304ea44d2114381389b7a98ebe2dedb9fc0" +checksum = "0c92880c09b37d5bdff2ced22e0911cce75e3e425f51783628481d478aa2a80d" dependencies = [ "anyhow", "enum-iterator", @@ -3544,16 +3897,16 @@ dependencies = [ [[package]] name = "snarkvm-console-network-environment" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd75285546ba5ad34a7b670cd106993a146fd4648ba83341b57c92103759184" +checksum = "ee1aeabebbda7b45b66196cdd9db456d154625b6b3233c477536b82e46024688" dependencies = [ "anyhow", "bech32", "itertools 0.14.0", "nom", "num-traits", - "rand", + "rand 0.8.5", "serde", "snarkvm-curves", "snarkvm-fields", @@ -3563,9 +3916,9 @@ dependencies = [ [[package]] name = "snarkvm-console-program" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a724b241707906b83dc4705e2d339797c0d7c69ec2d240a9f405d35f426a9b7" +checksum = "ff7a0ff48530b8392268dec61f9231b2eb290624d6f58246ada83eaca7bcde99" dependencies = [ "enum-iterator", "enum_index", @@ -3585,9 +3938,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6793dd7c4c6478c159fda55a6d070b883480cf52cac76284833c20b1ac47e2e3" +checksum = "2047f4712e7de64699e401c08d80aa11aefbda4bb5a3b97cfe0181b31cb482c8" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-address", @@ -3601,9 +3954,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types-address" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db5700d0b3f8e37b13168f97ea89dbbed7940fd7457c4a6615ce45cf178fb9a" +checksum = "cc581d795614ffa23dbf737c44413caf7b25a62845f38649ba00a61be6f124ec" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3613,18 +3966,18 @@ dependencies = [ [[package]] name = "snarkvm-console-types-boolean" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802355742f003b23d5c8b5cda70c7cf7bb1f9b53073c7f00b936e95b0e2e3e16" +checksum = "740afa0e3018eb8048f1d2351b92c163214a6d16b73513f9f4fe0de53d8d977c" dependencies = [ "snarkvm-console-network-environment", ] [[package]] name = "snarkvm-console-types-field" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7147389112fce94fdddf8d055333bbf70c98f972396d6cef7460ce1ff2d48d64" +checksum = "93d92c4e9dddcdf25942903959d0402cad5baba3d56f0d09d22f4ee95fc24cb5" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3633,9 +3986,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types-group" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a4fcc6ef8d523d2767f0e313b5425aff5836b8c65cd9d7cf45a0696fbf45408" +checksum = "10ea02928ed85ea863cac8eb429ba92232d8e0aba7f111473b42665eedcc794f" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3645,9 +3998,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types-integers" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "811588494cb9b43c9e01f4864efa7518ba5ed89986cc033ec1af180d0d06ac78" +checksum = "ca7cfb62960c945521065a04cabf5b25cb9925027455c4f428d7613afc22a77d" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3657,9 +4010,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types-scalar" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45756f19569786bcdc739f81cd402a63c26b4136446c34805777dc00b6a625e4" +checksum = "593c61497ce4658e43d0829b6dd7ee57a01fe5069333f36bd14bcfa1cdeef680" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3669,9 +4022,9 @@ dependencies = [ [[package]] name = "snarkvm-console-types-string" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015dd2984f0d4ef4cf348392454ddf6eca95f9bf4fef904302c07b1dc389eb50" +checksum = "e8eb1d2a1275202adb50f1abae4d6afc1059950435f01bb884da435205bff96b" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3681,12 +4034,12 @@ dependencies = [ [[package]] name = "snarkvm-curves" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3417507f40657c8239e6fb82ddd73361c69d9cfd8a0bef134786c7047f97b3" +checksum = "68b8f4f8477fdd9fbab7bde40b5fd104993b6199227cd219af968384a8e8d657" dependencies = [ - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "rustc_version", "serde", "snarkvm-fields", @@ -3696,16 +4049,16 @@ dependencies = [ [[package]] name = "snarkvm-fields" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209bd033ac7c8cbbff9b0e62ff61deff371960e470d9677b867fe441a9b6a875" +checksum = "78912e74b5de1807326eb175e75331a9f5c195944746c362e9092dda6b54db8d" 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", @@ -3714,17 +4067,18 @@ dependencies = [ [[package]] name = "snarkvm-ledger" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad2637f59c18850a1cb25ff70cc39948fc85a36afe53e776ef6e8ec6a1e1998" +checksum = "7316e32fd40e028b214a9c3699a8c662e8202269d8378ab9d73f79388af110ce" dependencies = [ "aleo-std", "anyhow", "indexmap", "lru 0.16.2", "parking_lot", - "rand", - "rayon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon 1.11.0", "snarkvm-console", "snarkvm-ledger-authority", "snarkvm-ledger-block", @@ -3734,18 +4088,19 @@ dependencies = [ "snarkvm-ledger-query", "snarkvm-ledger-store", "snarkvm-synthesizer", + "snarkvm-utilities", "time", "tracing", ] [[package]] name = "snarkvm-ledger-authority" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce477d2af8d466aa7d580fe6ec1c956c60bb2d6015488b03c47801039e1a6a99" +checksum = "f3a20386597ffd5550e536265c0a24d823db995df8d555ab59d55b335d823cd2" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-subdag", @@ -3753,13 +4108,13 @@ dependencies = [ [[package]] name = "snarkvm-ledger-block" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b43eccc11644d93e872a3fb12489a8c111ed7749f9e268604ab0326b1fdb79a" +checksum = "39d4687d54811d18d6922e167e432c2f78be2fc31ff849098d90b5a08f56a741" dependencies = [ "anyhow", "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-authority", @@ -3776,12 +4131,12 @@ dependencies = [ [[package]] name = "snarkvm-ledger-committee" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0c8564df9e34e9ae2af048ecb52b42a4c55ee43d9960ee617319cd85a4014e" +checksum = "2678d6e0bc202ea821638836c36d129df1f4aec86c19681edffbf0d7ce14bb04" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-batch-header", @@ -3789,9 +4144,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db5f21e643fa9763a318ae406b3cb4bfd854a64dc038d947d26222a76168cfb" +checksum = "f00182f1ef4f1d804d884784a3de91246fe3f4b53231434b02f15f35b2146638" dependencies = [ "snarkvm-ledger-narwhal-batch-certificate", "snarkvm-ledger-narwhal-batch-header", @@ -3803,12 +4158,12 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-certificate" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ed2fc97807b65dbcd64b926a23efc6682080a81840e2edd84c1c2ba987eff6" +checksum = "9a87acbd36d5851fc746550fc190d37ce56660a48be9659bcc4c0de08ba4ea7f" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-batch-header", @@ -3817,12 +4172,12 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-header" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfbf6ef6f8100803994160c0b18ccb50a95e333d863008b82cbfc2dcbe0d891a" +checksum = "1c94988348c23db830c3431528af45a6c876a2bf1142fcd15f42d128a496762b" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-narwhal-transmission-id", @@ -3830,9 +4185,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-data" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2387a11394f4ac4fe027da2d90ec4b1674226304c583068f3d81befa2f271e" +checksum = "41c37c79d6a7f934ed19a7f32391ea1c77567991f3a29b1dfe138b4b8ef27b41" dependencies = [ "bytes", "serde_json", @@ -3842,12 +4197,12 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-subdag" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba2891882c9299b315267cfe1bbb66001a74bdb241bdba77efb3a90166383cc" +checksum = "98fe2242ed6a26b4fe3d52888b392b4560e3ec466ea97e7d06d4083068d9113f" dependencies = [ "indexmap", - "rayon", + "rayon 1.11.0", "serde_json", "snarkvm-console", "snarkvm-ledger-committee", @@ -3858,9 +4213,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fa4f4091adaec015d8cbdbac68efb700397f4f101b1ec8f6992bbd1df7c6cd" +checksum = "5f5d7f2d5e27d90ff886c9ce773d85283297027da314bf6ae76bcce09fc76dbf" dependencies = [ "bytes", "serde_json", @@ -3872,9 +4227,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission-id" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e43fa7849e5d15e7ecaed1a46b4e12e3cb288ad072e4acce3952f0bf503b0283" +checksum = "850f880f898929b3ad24b6e403c6edeec8c35f40040c5f89c1ae2ef539bf0293" dependencies = [ "snarkvm-console", "snarkvm-ledger-puzzle", @@ -3882,9 +4237,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a12aa22b79f751330cb8119ef559efa9317fcf299f7cebed20d0db8cc2c4452" +checksum = "e94e53be712268f4d0994899fa2d5143606da62e1946265607abe58fa7a6723c" dependencies = [ "aleo-std", "anyhow", @@ -3892,9 +4247,9 @@ dependencies = [ "indexmap", "lru 0.16.2", "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", @@ -3902,9 +4257,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle-epoch" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be3ae1abb546466b9f061e83ab28b4e3655e8df16d9d69d4b1df8bb382c89550" +checksum = "45c2b866424dba58368d47e85e4529e4dbae68cf346ab1f9b7e2dd08631c5697" dependencies = [ "aleo-std", "anyhow", @@ -3912,9 +4267,9 @@ dependencies = [ "indexmap", "lru 0.16.2", "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", @@ -3925,9 +4280,9 @@ dependencies = [ [[package]] name = "snarkvm-ledger-query" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3e27386cf904135df0e667de520435c1e2df9381ec5aed751e831c9e0d5f54" +checksum = "92b9a6594198d17477adc72a8fbffa495e0c0193dd8fc36e632f787d5b98c694" dependencies = [ "anyhow", "async-trait", @@ -3943,16 +4298,16 @@ dependencies = [ [[package]] name = "snarkvm-ledger-store" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef37e97b6f61947982c51abb4f67e22dbde9f10b1384c76166bd6f72b479cd38" +checksum = "4c125333fa216ae69b3f90563a2d06f47511d553bc0f951771709177cfaa1638" dependencies = [ "aleo-std-storage", "anyhow", "bincode", "indexmap", "parking_lot", - "rayon", + "rayon 1.11.0", "serde", "serde_json", "snarkvm-console", @@ -3968,9 +4323,9 @@ dependencies = [ [[package]] name = "snarkvm-parameters" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55971406e99e74d427a22525e6f7e1bccd02de35b24d2f77d0f8dab6bbf90b54" +checksum = "7b1f5f415330dbb5c5921ef6d05962b5d18f239c12d4f1a12795a592ecde6038" dependencies = [ "aleo-std", "anyhow", @@ -3981,7 +4336,7 @@ dependencies = [ "lazy_static", "parking_lot", "paste", - "rand", + "rand 0.8.5", "serde_json", "sha2", "snarkvm-curves", @@ -3991,9 +4346,9 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e4452b9b0517e73daea7f8e89e5e07f81546d3d887992448bd3df3afd066dd" +checksum = "6f0092bc65216609a180c01e8a03b2a527d6b527e8776ce71785b932f901893e" dependencies = [ "aleo-std", "anyhow", @@ -4001,8 +4356,8 @@ dependencies = [ "itertools 0.14.0", "lru 0.16.2", "parking_lot", - "rand", - "rayon", + "rand 0.8.5", + "rayon 1.11.0", "serde_json", "snarkvm-algorithms", "snarkvm-circuit", @@ -4023,17 +4378,17 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-process" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90d40cd0ad6737ce54092636f3251160d5b835c6863ea20ccf9eb6e1220f55aa" +checksum = "28ceadf64062805b4a48b298c206a9f5a4bb12032a9a60465ef1e0a5766cdf77" 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", @@ -4048,16 +4403,16 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-program" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f144a0df16c0ce72a6ead9943ea00b1aaebddff39d1bb002c651f7d5e3f0bc22" +checksum = "cdc32136ef3ac69aaeab040e11e4a0bdc8c00dbae778c0d3b65120d179e44eb9" 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", @@ -4068,9 +4423,9 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-snark" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9b08d9097c476e878eff221bb5d3e2c8f885aa3234308746fdc44d29bd4e1f" +checksum = "175dbc6a6d7cbf188397b81c545323bed27dab554a40e3a6261988f0b1fdca0a" dependencies = [ "bincode", "serde_json", @@ -4082,18 +4437,18 @@ dependencies = [ [[package]] name = "snarkvm-utilities" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06276676035bac7fe1a3f8141f0849d9998a22e032070c3a75816a8719f4573" +checksum = "9b062dc2351b888db6ea293e2ee294b4069c5b9eda242f8d336f08f2ea95150d" dependencies = [ "aleo-std", "anyhow", "bincode", "num-bigint", "num_cpus", - "rand", + "rand 0.8.5", "rand_xorshift", - "rayon", + "rayon 1.11.0", "serde", "serde_json", "smol_str", @@ -4105,13 +4460,13 @@ dependencies = [ [[package]] name = "snarkvm-utilities-derives" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad221af8d6c8bcfea7b1050c65dc835850780c42fb46cadd92d933fb0717c285" +checksum = "4a60e21b9d249446399f4c67bf2ca12e1e10bb2539a1812df3202d235213d5b3" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4124,6 +4479,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" @@ -4181,9 +4545,9 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck", "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "rustversion", - "syn 2.0.107", + "syn 2.0.109", ] [[package]] @@ -4210,18 +4574,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.107" +version = "2.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" +checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f" dependencies = [ "proc-macro2", - "quote 1.0.41", + "quote 1.0.42", "unicode-ident", ] @@ -4250,8 +4614,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4341,8 +4705,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4352,8 +4716,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4407,9 +4771,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -4439,11 +4803,25 @@ 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.42", + "syn 2.0.109", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -4466,9 +4844,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -4490,6 +4868,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -4508,6 +4887,7 @@ dependencies = [ "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -4522,12 +4902,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.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4540,8 +4937,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4571,10 +4968,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -4585,6 +4986,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" @@ -4593,9 +5004,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-segmentation" @@ -4767,9 +5178,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -4778,25 +5189,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -4807,41 +5204,41 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ - "quote 1.0.41", + "quote 1.0.42", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", - "wasm-bindgen-backend", + "quote 1.0.42", + "syn 2.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -4859,9 +5256,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] @@ -4929,8 +5326,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -4940,8 +5337,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -5176,17 +5573,16 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -5194,13 +5590,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", "synstructure", ] @@ -5220,8 +5616,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -5240,8 +5636,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", "synstructure", ] @@ -5261,15 +5657,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -5278,9 +5674,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -5289,13 +5685,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", - "quote 1.0.41", - "syn 2.0.107", + "quote 1.0.42", + "syn 2.0.109", ] [[package]] @@ -5328,9 +5724,9 @@ dependencies = [ [[package]] name = "zopfli" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" dependencies = [ "bumpalo", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index e4edd684aa..c59758b35b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,18 +90,31 @@ path = "./test-framework" version = "=3.3.1" [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" ] @@ -112,6 +125,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 @@ -121,11 +140,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" ] @@ -145,15 +167,29 @@ version = "3.1.1" version = "0.10.9" [workspace.dependencies.snarkvm] -version = "4.3.0" -features = [ "test_consensus_heights" ] +version = "4.4.0" +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" @@ -207,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" @@ -241,6 +286,9 @@ version = "1.0.5" [dependencies.indexmap] workspace = true +[dependencies.is-terminal] +version = "0.4" + [dependencies.itertools] workspace = true @@ -265,6 +313,9 @@ workspace = true [dependencies.regex] workspace = true +[dependencies.reqwest] +workspace = true + [dependencies.rpassword] version = "7.4.0" @@ -285,7 +336,7 @@ workspace = true [dependencies.snarkvm] workspace = true -features = [ "circuit", "console" ] +features = ["circuit", "console"] [dependencies.sys-info] version = "0.9.1" @@ -293,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/interpreter/src/cursor_aleo.rs b/interpreter/src/cursor_aleo.rs index c2ff463c0a..94b3a7bf4c 100644 --- a/interpreter/src/cursor_aleo.rs +++ b/interpreter/src/cursor_aleo.rs @@ -148,6 +148,7 @@ impl Cursor { } } Operand::BlockHeight => self.block_height.into(), + Operand::BlockTimestamp => self.block_timestamp.into(), Operand::NetworkID => todo!(), Operand::Checksum(_) => todo!(), Operand::Edition(_) => todo!(), diff --git a/leo/cli/cli.rs b/leo/cli/cli.rs index 05543b23dc..c4818a1cd4 100644 --- a/leo/cli/cli.rs +++ b/leo/cli/cli.rs @@ -77,6 +77,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)] @@ -148,7 +153,10 @@ pub fn run_with_args(cli: CLI) -> Result<()> { // Initialize the `.env` file. dotenvy::dotenv().ok(); - if !cli.quiet { + // Skip logger initialization for devnode -- it uses it's own logger. + let is_devnode = matches!(&cli.command, Commands::Devnode { .. }); + + if !cli.quiet && !is_devnode { // Init logger with optional debug flag. logger::init_logger("leo", match cli.debug { false => 1, @@ -175,6 +183,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> { Commands::Clean { command } => command.try_execute(context), Commands::Deploy { command } => command.try_execute(context), Commands::Devnet { command } => command.try_execute(context), + Commands::Devnode { command } => command.try_execute(context), Commands::Run { command } => command.try_execute(context), Commands::Test { command } => command.try_execute(context), Commands::Execute { command } => command.try_execute(context), diff --git a/leo/cli/commands/common/options.rs b/leo/cli/commands/common/options.rs index 257ed73298..455f6984e5 100644 --- a/leo/cli/commands/common/options.rs +++ b/leo/cli/commands/common/options.rs @@ -116,8 +116,7 @@ pub struct EnvOptions { pub struct FeeOptions { #[clap( long, - help = "[UNUSED] Base fees in microcredits, delimited by `|`, and used in order. The fees must either be valid `u64` or `default`. Defaults to automatic calculation.", - hide = true, + help = "Base fees in microcredits, delimited by `|`, and used in order. The fees must either be valid `u64` or `default`. Defaults to automatic calculation.", value_delimiter = '|', value_parser = parse_amount )] @@ -316,6 +315,7 @@ pub fn number_to_consensus_version(index: usize) -> ConsensusVersion { 9 => ConsensusVersion::V9, 10 => ConsensusVersion::V10, 11 => ConsensusVersion::V11, + 12 => ConsensusVersion::V12, _ => panic!("Invalid consensus version: {index}"), } } diff --git a/leo/cli/commands/deploy.rs b/leo/cli/commands/deploy.rs index 7bbab99cf9..9f3cfc74f6 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 { @@ -92,25 +102,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, @@ -266,7 +276,7 @@ fn handle_deploy( // For each of the programs, generate a deployment transaction. let mut transactions = Vec::new(); - for Task { id, program, priority_fee, record, .. } in local { + for Task { id, program, edition, priority_fee, record, .. } 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. @@ -287,27 +297,100 @@ 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"); - // Print the deployment stats. - print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?; - // Save the transaction. - transactions.push((id, transaction)); + // Get the deployment. + let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); + // Print the deployment stats. + print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?; + // Save the transaction. + transactions.push((id, transaction)); + } + + 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..92ca95eb3f --- /dev/null +++ b/leo/cli/commands/devnode/advance.rs @@ -0,0 +1,62 @@ +// 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(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("http://localhost:3030/testnet/block/create") + .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..43fd87c4aa --- /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 { + hanlde_devnode(self, context) + } +} + +// A helper function to handle the Devnode command based on the subcommand provided. +fn hanlde_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..f12ac01edc --- /dev/null +++ b/leo/cli/commands/devnode/start.rs @@ -0,0 +1,127 @@ +// 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) listener_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.listener_addr.parse().map_err(|e| { + CliError::custom(format!("Failed to parse listener address '{}': {}", command.listener_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.clone()).map_err(|e| { + CliError::custom(format!("Failed to read genesis block file '{}': {}", command.genesis_path, e)) + })?)? + } else { + 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.clone()) + .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 will initialize 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("http://localhost:3030/testnet/block/create") + .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 bf13475231..5e774578fe 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. @@ -290,6 +292,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. @@ -341,34 +344,82 @@ 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}..."); - // Print the execution stats. - print_execution_stats::( - &vm, - &program_name, - transaction.execution().expect("Expected execution"), - priority_fee, - consensus_version, - )?; + // 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, + )?; + + // Print the execution stats. + print_execution_stats::( + &vm, + &program_name, + transaction.execution().expect("Expected execution"), + priority_fee, + consensus_version, + )?; + + ("execution", Box::new(transaction), response) + }; // Print the transaction. // 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. @@ -378,9 +429,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}")))?; @@ -399,6 +450,7 @@ fn handle_execute( // If the `broadcast` option is set, broadcast each deployment transaction to the network. if command.action.broadcast { println!("📡 Broadcasting execution for {program_name}..."); + let transaction = output; // Get and confirm the fee with the user. let mut fee_id = None; if let Some(fee) = transaction.fee_transition() { @@ -501,6 +553,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()); @@ -525,6 +578,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 e1a69e5fc1..ab14d4bb7c 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, @@ -293,19 +302,90 @@ fn handle_upgrade( for Task { id, program, priority_fee, record, .. } 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"); - // Print the deployment stats. - print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?; - // Validate the deployment limits. - validate_deployment_limits(deployment, &id, &network)?; - // Save the transaction. - transactions.push((id, transaction)); + // Get the deployment. + let deployment = transaction.deployment().expect("Expected a deployment in the transaction"); + // Print the deployment stats. + print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?; + // Validate the deployment limits. + validate_deployment_limits(deployment, &id, &network)?; + // Save the transaction. + transactions.push((id, transaction)); + } } // Add the program to the VM. vm.process().write().add_program(&program)?; @@ -488,6 +568,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, } } }