From 167bbca10441ad0d592328bbe2df4b799224dcea Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:19:52 +0500 Subject: [PATCH 1/9] feat(faucet): migrate to axum from actix (#511) --- CHANGELOG.md | 3 +- Cargo.lock | 585 ++++--------------------------------- Cargo.toml | 2 +- bin/faucet/Cargo.toml | 12 +- bin/faucet/src/client.rs | 73 +++-- bin/faucet/src/config.rs | 6 - bin/faucet/src/errors.rs | 69 +++-- bin/faucet/src/handlers.rs | 83 ++++-- bin/faucet/src/main.rs | 88 +++--- bin/faucet/src/state.rs | 19 +- 10 files changed, 266 insertions(+), 674 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee919517..b9bd903ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ - Improve `--version` by adding build metadata (#495). - [BREAKING] Introduced additional limits for note/account number (#503). - [BREAKING] Removed support for basic wallets in genesis creation (#510). -- Added `GetAccountStates` endpoint (#506). +- Added `GetAccountProofs` endpoint (#506). +- Migrated faucet from actix-web to axum (#511). ## 0.5.1 (2024-09-12) diff --git a/Cargo.lock b/Cargo.lock index cf34633e8..e110537a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,216 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "actix-codec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-cors" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e772b3bcafe335042b5db010ab7c09013dad6eac4915c91d8d50902769f331" -dependencies = [ - "actix-utils", - "actix-web", - "derive_more", - "futures-util", - "log", - "once_cell", - "smallvec", -] - -[[package]] -name = "actix-http" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "ahash", - "base64", - "bitflags", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "futures-core", - "h2 0.3.26", - "http 0.2.12", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "actix-router" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" -dependencies = [ - "bytestring", - "cfg-if", - "http 0.2.12", - "regex", - "regex-lite", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" -dependencies = [ - "futures-core", - "tokio", -] - -[[package]] -name = "actix-server" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" -dependencies = [ - "futures-core", - "paste", - "pin-project-lite", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] - -[[package]] -name = "actix-web" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "ahash", - "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "futures-core", - "futures-util", - "impl-more", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite", - "regex", - "regex-lite", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2", - "time", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "actix-web-static-files" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf6d1ef6d7a60e084f9e0595e2a5234abda14e76c105ecf8e2d0e8800c41a1f" -dependencies = [ - "actix-web", - "derive_more", - "futures-util", - "static-files", -] - [[package]] name = "addr2line" version = "0.24.1" @@ -234,7 +24,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", "once_cell", "version_check", "zerocopy", @@ -249,21 +38,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -355,15 +129,6 @@ dependencies = [ "term", ] -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - [[package]] name = "async-stream" version = "0.3.5" @@ -420,17 +185,19 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "http-body-util", + "hyper", + "hyper-util", "itoa", "matchit", "memchr", @@ -439,22 +206,27 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", "sync_wrapper 1.0.1", + "tokio", "tower 0.5.1", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-core" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "http-body-util", "mime", @@ -463,6 +235,7 @@ dependencies = [ "sync_wrapper 1.0.1", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -564,27 +337,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "brotli" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -609,15 +361,6 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" -[[package]] -name = "bytestring" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" -dependencies = [ - "bytes", -] - [[package]] name = "camino" version = "1.1.9" @@ -763,23 +506,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -795,15 +521,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -960,19 +677,6 @@ dependencies = [ "syn", ] -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.1", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -1046,15 +750,6 @@ dependencies = [ "log", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1071,12 +766,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1117,16 +806,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" -[[package]] -name = "flate2" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1201,7 +880,6 @@ dependencies = [ "futures-task", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -1250,25 +928,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.5.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.6" @@ -1280,7 +939,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http", "indexmap 2.5.0", "slab", "tokio", @@ -1330,17 +989,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -1359,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -1370,7 +1018,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "pin-project-lite", ] @@ -1396,8 +1044,8 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2", + "http", "http-body", "httparse", "httpdate", @@ -1430,7 +1078,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http", "http-body", "hyper", "pin-project-lite", @@ -1469,22 +1117,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-more" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d" - [[package]] name = "indenter" version = "0.3.3" @@ -1616,12 +1248,6 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - [[package]] name = "lazy_static" version = "1.5.0" @@ -1684,23 +1310,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - [[package]] name = "lock_api" version = "0.4.12" @@ -1857,25 +1466,27 @@ dependencies = [ name = "miden-faucet" version = "0.6.0" dependencies = [ - "actix-cors", - "actix-web", - "actix-web-static-files", - "async-mutex", + "axum", "clap", - "derive_more", "figment", + "http", + "http-body-util", "miden-lib", "miden-node-proto", "miden-node-utils", "miden-objects", "miden-tx", + "mime", "rand", "rand_chacha", "serde", "static-files", "thiserror", + "tokio", "toml", "tonic", + "tower 0.5.1", + "tower-http 0.6.1", "tracing", ] @@ -2250,7 +1861,6 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "log", "wasi", "windows-sys 0.52.0", ] @@ -2453,12 +2063,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "path-matchers" version = "1.0.2" @@ -2852,12 +2456,6 @@ dependencies = [ "regex-syntax 0.8.4", ] -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - [[package]] name = "regex-syntax" version = "0.6.29" @@ -3038,6 +2636,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.8" @@ -3059,17 +2667,6 @@ dependencies = [ "serde", ] -[[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]] name = "sha3" version = "0.10.8" @@ -3095,15 +2692,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "siphasher" version = "0.3.11" @@ -3356,21 +2944,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.40.0" @@ -3381,9 +2954,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -3469,8 +3040,8 @@ dependencies = [ "axum", "base64", "bytes", - "h2 0.4.6", - "http 1.1.0", + "h2", + "http", "http-body", "http-body-util", "hyper", @@ -3510,13 +3081,13 @@ checksum = "5299dd20801ad736dccb4a5ea0da7376e59cd98f213bf1c3d478cf53f4834b58" dependencies = [ "base64", "bytes", - "http 1.1.0", + "http", "http-body", "http-body-util", "pin-project", "tokio-stream", "tonic", - "tower-http", + "tower-http 0.5.2", "tower-layer", "tower-service", "tracing", @@ -3552,8 +3123,10 @@ dependencies = [ "futures-util", "pin-project-lite", "sync_wrapper 0.1.2", + "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -3564,7 +3137,7 @@ checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags", "bytes", - "http 1.1.0", + "http", "http-body", "http-body-util", "pin-project-lite", @@ -3572,6 +3145,22 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "bitflags", + "bytes", + "http", + "http-body", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -3723,12 +3312,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.13" @@ -3741,15 +3324,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.14" @@ -3762,17 +3336,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "utf8parse" version = "0.2.2" @@ -4357,31 +3920,3 @@ dependencies = [ "quote", "syn", ] - -[[package]] -name = "zstd" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml index 7e2f0c5cc..656515f39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ miden-stdlib = { version = "0.10", default-features = false } miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } prost = { version = "0.13" } thiserror = { version = "1.0" } -tokio = { version = "1.40" } +tokio = { version = "1.40", features = ["rt-multi-thread"] } tokio-stream = { version = "0.1" } tonic = { version = "0.12" } tracing = { version = "0.1" } diff --git a/bin/faucet/Cargo.toml b/bin/faucet/Cargo.toml index f08e37729..fc03a81ad 100644 --- a/bin/faucet/Cargo.toml +++ b/bin/faucet/Cargo.toml @@ -17,25 +17,27 @@ repository.workspace = true testing = ["miden-objects/testing", "miden-lib/testing"] [dependencies] -actix-cors = "0.7" -actix-web = "4.8" -actix-web-static-files = "4.0" -async-mutex = "1.4" +axum = { version = "0.7", features = ["tokio"] } clap = { version = "4.5", features = ["derive", "string"] } -derive_more = "0.99" figment = { version = "0.10", features = ["toml", "env"] } +http = "1.1" +http-body-util = "0.1" miden-lib = { workspace = true, features = ["concurrent"] } miden-node-proto = { workspace = true } miden-node-utils = { workspace = true } miden-objects = { workspace = true , features = ["concurrent"] } miden-tx = { workspace = true, features = ["concurrent"] } +mime = "0.3" rand = { version = "0.8" } rand_chacha = "0.3" serde = { version = "1.0", features = ["derive"] } static-files = "0.2" thiserror = { workspace = true } +tokio = { workspace = true } toml = { version = "0.8" } tonic = { workspace = true } +tower = "0.5" +tower-http = { version = "0.6", features = ["cors", "set-header", "trace"] } tracing = { workspace = true } [build-dependencies] diff --git a/bin/faucet/src/client.rs b/bin/faucet/src/client.rs index 595709b5c..d02f4a138 100644 --- a/bin/faucet/src/client.rs +++ b/bin/faucet/src/client.rs @@ -30,7 +30,10 @@ use rand::{rngs::StdRng, thread_rng, Rng}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use tonic::transport::Channel; -use crate::{config::FaucetConfig, errors::FaucetError}; +use crate::{ + config::FaucetConfig, + errors::{InitError, ProcessError}, +}; pub const DISTRIBUTE_FUNGIBLE_ASSET_SCRIPT: &str = include_str!("transaction_scripts/distribute_fungible_asset.masm"); @@ -52,7 +55,7 @@ unsafe impl Send for FaucetClient {} unsafe impl Sync for FaucetClient {} impl FaucetClient { - pub async fn new(config: FaucetConfig) -> Result { + pub async fn new(config: FaucetConfig) -> Result { let (rpc_api, root_block_header, root_chain_mmr) = initialize_faucet_client(config.clone()).await?; @@ -87,9 +90,9 @@ impl FaucetClient { target_account_id: AccountId, is_private_note: bool, asset_amount: u64, - ) -> Result<(ExecutedTransaction, Note), FaucetError> { + ) -> Result<(ExecutedTransaction, Note), ProcessError> { let asset = FungibleAsset::new(self.id, asset_amount) - .map_err(|err| FaucetError::InternalServerError(err.to_string()))?; + .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; let note_type = if is_private_note { NoteType::Private @@ -105,7 +108,7 @@ impl FaucetClient { Default::default(), &mut self.rng, ) - .map_err(|err| FaucetError::InternalServerError(err.to_string()))?; + .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; let transaction_args = build_transaction_arguments(&output_note, note_type, asset)?; @@ -113,7 +116,7 @@ impl FaucetClient { .executor .execute_transaction(self.id, 0, &[], transaction_args) .map_err(|err| { - FaucetError::InternalServerError(format!("Failed to execute transaction: {}", err)) + ProcessError::InternalServerError(format!("Failed to execute transaction: {err}")) })?; Ok((executed_tx, output_note)) @@ -123,27 +126,32 @@ impl FaucetClient { pub async fn prove_and_submit_transaction( &mut self, executed_tx: ExecutedTransaction, - ) -> Result { - let transaction_prover = LocalTransactionProver::new(ProvingOptions::default()); - + ) -> Result { let delta = executed_tx.account_delta().clone(); - let proven_transaction = transaction_prover.prove(executed_tx).map_err(|err| { - FaucetError::InternalServerError(format!("Failed to prove transaction: {}", err)) - })?; + // Prepare request with proven transaction. + // This is needed to be in a separated code block in order to release reference to avoid + // borrow checker error. + let request = { + let transaction_prover = LocalTransactionProver::new(ProvingOptions::default()); - let request = SubmitProvenTransactionRequest { - transaction: proven_transaction.to_bytes(), + let proven_transaction = transaction_prover.prove(executed_tx).map_err(|err| { + ProcessError::InternalServerError(format!("Failed to prove transaction: {err}")) + })?; + + SubmitProvenTransactionRequest { + transaction: proven_transaction.to_bytes(), + } }; let response = self .rpc_api .submit_proven_transaction(request) .await - .map_err(|err| FaucetError::InternalServerError(err.to_string()))?; + .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; self.data_store.update_faucet_account(&delta).map_err(|err| { - FaucetError::InternalServerError(format!("Failed to update account: {}", err)) + ProcessError::InternalServerError(format!("Failed to update account: {err}")) })?; Ok(response.into_inner().block_height) @@ -181,11 +189,11 @@ impl FaucetDataStore { } /// Updates the stored faucet account with the provided delta. - fn update_faucet_account(&mut self, delta: &AccountDelta) -> Result<(), FaucetError> { + fn update_faucet_account(&mut self, delta: &AccountDelta) -> Result<(), ProcessError> { self.faucet_account .borrow_mut() .apply_delta(delta) - .map_err(|err| FaucetError::InternalServerError(err.to_string())) + .map_err(|err| ProcessError::InternalServerError(err.to_string())) } } @@ -221,13 +229,13 @@ impl DataStore for FaucetDataStore { /// Builds a new faucet account with the provided configuration. /// /// Returns the created account, its seed, and the secret key used to sign transactions. -fn build_account(config: FaucetConfig) -> Result<(Account, Word, SecretKey), FaucetError> { +fn build_account(config: FaucetConfig) -> Result<(Account, Word, SecretKey), InitError> { let token_symbol = TokenSymbol::new(config.token_symbol.as_str()) - .map_err(|err| FaucetError::AccountCreationError(err.to_string()))?; + .map_err(|err| InitError::AccountCreationError(err.to_string()))?; let seed: [u8; 32] = [0; 32]; - // Instantiate keypair and authscheme + // Instantiate keypair and auth scheme let mut rng = ChaCha20Rng::from_seed(seed); let secret = SecretKey::with_rng(&mut rng); let auth_scheme = AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }; @@ -237,11 +245,11 @@ fn build_account(config: FaucetConfig) -> Result<(Account, Word, SecretKey), Fau token_symbol, config.decimals, Felt::try_from(config.max_supply) - .map_err(|err| FaucetError::InternalServerError(err.to_string()))?, + .map_err(|err| InitError::AccountCreationError(err.to_string()))?, AccountStorageMode::Private, auth_scheme, ) - .map_err(|err| FaucetError::AccountCreationError(err.to_string()))?; + .map_err(|err| InitError::AccountCreationError(err.to_string()))?; Ok((faucet_account, account_seed, secret)) } @@ -249,26 +257,27 @@ fn build_account(config: FaucetConfig) -> Result<(Account, Word, SecretKey), Fau /// Initializes the faucet client by connecting to the node and fetching the root block header. pub async fn initialize_faucet_client( config: FaucetConfig, -) -> Result<(ApiClient, BlockHeader, ChainMmr), FaucetError> { +) -> Result<(ApiClient, BlockHeader, ChainMmr), InitError> { let endpoint = tonic::transport::Endpoint::try_from(config.node_url.clone()) - .map_err(|_| FaucetError::InternalServerError("Failed to connect to node.".to_string()))? + .map_err(|_| InitError::ClientInitFailed("Failed to connect to node.".to_string()))? .timeout(Duration::from_millis(config.timeout_ms)); let mut rpc_api = ApiClient::connect(endpoint) .await - .map_err(|err| FaucetError::InternalServerError(err.to_string()))?; + .map_err(|err| InitError::ClientInitFailed(err.to_string()))?; let request = GetBlockHeaderByNumberRequest { block_num: Some(0), include_mmr_proof: Some(true), }; - let response = rpc_api.get_block_header_by_number(request).await.map_err(|err| { - FaucetError::InternalServerError(format!("Failed to get block header: {}", err)) - })?; + let response = rpc_api + .get_block_header_by_number(request) + .await + .map_err(|err| InitError::ClientInitFailed(format!("Failed to get block header: {err}")))?; let root_block_header = response.into_inner().block_header.unwrap(); let root_block_header: BlockHeader = root_block_header.try_into().map_err(|err| { - FaucetError::InternalServerError(format!("Failed to parse block header: {}", err)) + InitError::ClientInitFailed(format!("Failed to parse block header: {err}")) })?; let root_chain_mmr = ChainMmr::new( @@ -287,7 +296,7 @@ fn build_transaction_arguments( output_note: &Note, note_type: NoteType, asset: FungibleAsset, -) -> Result { +) -> Result { let recipient = output_note .recipient() .digest() @@ -310,7 +319,7 @@ fn build_transaction_arguments( let script = TransactionScript::compile(script, vec![], TransactionKernel::assembler()) .map_err(|err| { - FaucetError::InternalServerError(format!("Failed to compile script: {}", err)) + ProcessError::InternalServerError(format!("Failed to compile script: {err}")) })?; let mut transaction_args = TransactionArgs::new(Some(script), None, AdviceMap::new()); diff --git a/bin/faucet/src/config.rs b/bin/faucet/src/config.rs index 16ce094eb..1e443585a 100644 --- a/bin/faucet/src/config.rs +++ b/bin/faucet/src/config.rs @@ -25,12 +25,6 @@ pub struct FaucetConfig { pub max_supply: u64, } -impl FaucetConfig { - pub fn endpoint_url(&self) -> String { - self.endpoint.to_string() - } -} - impl Display for FaucetConfig { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( diff --git a/bin/faucet/src/errors.rs b/bin/faucet/src/errors.rs index 4e167e855..50777c719 100644 --- a/bin/faucet/src/errors.rs +++ b/bin/faucet/src/errors.rs @@ -1,47 +1,62 @@ -use actix_web::{ - error, - http::{header::ContentType, StatusCode}, - HttpResponse, +use axum::{ + http::{header, StatusCode}, + response::{IntoResponse, Response}, }; use thiserror::Error; #[derive(Debug, Error)] -pub enum FaucetError { +pub enum InitError { #[error("Failed to start faucet: {0}")] - StartError(String), + FaucetFailedToStart(String), - #[error("Client has submitted a bad request: {0}")] - BadRequest(String), + #[error("Failed to initialize client: {0}")] + ClientInitFailed(String), #[error("Failed to configure faucet: {0}")] ConfigurationError(String), + #[error("Failed to create Miden account: {0}")] + AccountCreationError(String), +} + +#[derive(Debug, Error)] +pub enum ProcessError { + #[error("Client has submitted a bad request: {0}")] + BadRequest(String), + #[error("Server has encountered an internal error: {0}")] InternalServerError(String), - #[error("Failed to create Miden account: {0}")] - AccountCreationError(String), + #[error("Page not found: {0}")] + NotFound(String), } -impl error::ResponseError for FaucetError { - fn error_response(&self) -> HttpResponse { - let message = match self { - FaucetError::StartError(msg) => msg.to_string(), - FaucetError::BadRequest(msg) => msg.to_string(), - FaucetError::ConfigurationError(msg) => msg.to_string(), - FaucetError::InternalServerError(msg) => msg.to_string(), - FaucetError::AccountCreationError(msg) => msg.to_string(), - }; - - HttpResponse::build(self.status_code()) - .insert_header(ContentType::html()) - .body(message.to_owned()) +impl ProcessError { + fn status_code(&self) -> StatusCode { + match *self { + Self::BadRequest(_) => StatusCode::BAD_REQUEST, + Self::NotFound(_) => StatusCode::NOT_FOUND, + Self::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR, + } } - fn status_code(&self) -> actix_web::http::StatusCode { - match *self { - FaucetError::BadRequest(_) => StatusCode::BAD_REQUEST, - _ => StatusCode::INTERNAL_SERVER_ERROR, + fn message(&self) -> String { + match self { + Self::BadRequest(msg) => msg, + Self::InternalServerError(_) => "Error processing request", + Self::NotFound(msg) => msg, } + .to_string() + } +} + +impl IntoResponse for ProcessError { + fn into_response(self) -> Response { + ( + self.status_code(), + [(header::CONTENT_TYPE, mime::TEXT_HTML_UTF_8.as_ref())], + self.message(), + ) + .into_response() } } diff --git a/bin/faucet/src/handlers.rs b/bin/faucet/src/handlers.rs index a98daec6f..5e51e4fda 100644 --- a/bin/faucet/src/handlers.rs +++ b/bin/faucet/src/handlers.rs @@ -1,60 +1,71 @@ -use actix_web::{get, http::header, post, web, HttpResponse, Result}; +use axum::{ + extract::{Path, State}, + http::{Response, StatusCode}, + response::IntoResponse, + Json, +}; +use http::header; +use http_body_util::Full; use miden_objects::{ accounts::AccountId, notes::{NoteDetails, NoteExecutionMode, NoteFile, NoteId, NoteTag}, utils::serde::Serializable, }; use serde::{Deserialize, Serialize}; +use tonic::body; use tracing::info; -use crate::{errors::FaucetError, state::FaucetState}; +use crate::{errors::ProcessError, state::FaucetState, COMPONENT}; #[derive(Deserialize)] -struct FaucetRequest { +pub struct FaucetRequest { account_id: String, is_private_note: bool, asset_amount: u64, } #[derive(Serialize)] -struct FaucetMetadataReponse { +pub struct FaucetMetadataReponse { id: String, asset_amount_options: Vec, } -#[get("/get_metadata")] -pub async fn get_metadata(state: web::Data) -> HttpResponse { +pub async fn get_metadata( + State(state): State, +) -> (StatusCode, Json) { let response = FaucetMetadataReponse { id: state.id.to_string(), asset_amount_options: state.config.asset_amount_options.clone(), }; - HttpResponse::Ok().json(response) + (StatusCode::OK, Json(response)) } -#[post("/get_tokens")] pub async fn get_tokens( - req: web::Json, - state: web::Data, -) -> Result { + State(state): State, + Json(req): Json, +) -> Result { info!( - "Received a request with account_id: {}, is_private_note: {}, asset_amount: {}", - req.account_id, req.is_private_note, req.asset_amount + target: COMPONENT, + account_id = %req.account_id, + is_private_note = %req.is_private_note, + asset_amount = %req.asset_amount, + "Received a request", ); // Check that the amount is in the asset amount options if !state.config.asset_amount_options.contains(&req.asset_amount) { - return Err(FaucetError::BadRequest("Invalid asset amount.".to_string()).into()); + return Err(ProcessError::BadRequest("Invalid asset amount".to_string())); } let mut client = state.client.lock().await; // Receive and hex user account id let target_account_id = AccountId::from_hex(req.account_id.as_str()) - .map_err(|err| FaucetError::BadRequest(err.to_string()))?; + .map_err(|err| ProcessError::BadRequest(err.to_string()))?; // Execute transaction - info!("Executing mint transaction for account."); + info!(target: COMPONENT, "Executing mint transaction for account."); let (executed_tx, created_note) = client.execute_mint_transaction( target_account_id, req.is_private_note, @@ -62,7 +73,7 @@ pub async fn get_tokens( )?; // Run transaction prover & send transaction to node - info!("Proving and submitting transaction."); + info!(target: COMPONENT, "Proving and submitting transaction."); let block_height = client.prove_and_submit_transaction(executed_tx).await?; let note_id: NoteId = created_note.id(); @@ -80,17 +91,33 @@ pub async fn get_tokens( } .to_bytes(); - info!("A new note has been created: {}", note_id); + info!(target: COMPONENT, %note_id, "A new note has been created"); // Send generated note to user - Ok(HttpResponse::Ok() - .content_type("application/octet-stream") - .append_header(header::ContentDisposition { - disposition: actix_web::http::header::DispositionType::Attachment, - parameters: vec![actix_web::http::header::DispositionParam::Filename( - "note.mno".to_string(), - )], - }) - .append_header(("Note-Id", note_id.to_string())) - .body(bytes)) + Response::builder() + .status(StatusCode::OK) + .header(header::CONTENT_TYPE, "application/octet-stream") + .header(header::CONTENT_DISPOSITION, "attachment; filename=note.mno") + .header("Note-Id", note_id.to_string()) + .body(body::boxed(Full::from(bytes))) + .map_err(|err| ProcessError::InternalServerError(err.to_string())) +} + +pub async fn get_index(state: State) -> Result { + get_static_file(state, Path("index.html".to_string())).await +} + +pub async fn get_static_file( + State(state): State, + Path(path): Path, +) -> Result { + info!(target: COMPONENT, path, "Serving static file"); + + let static_file = state.static_files.get(path.as_str()).ok_or(ProcessError::NotFound(path))?; + + Response::builder() + .status(StatusCode::OK) + .header(header::CONTENT_TYPE, static_file.mime_type) + .body(body::boxed(Full::from(static_file.data))) + .map_err(|err| ProcessError::InternalServerError(err.to_string())) } diff --git a/bin/faucet/src/main.rs b/bin/faucet/src/main.rs index 3247a4f31..f58f9f184 100644 --- a/bin/faucet/src/main.rs +++ b/bin/faucet/src/main.rs @@ -6,22 +6,24 @@ mod state; use std::{fs::File, io::Write, path::PathBuf}; -use actix_cors::Cors; -use actix_web::{ - middleware::{DefaultHeaders, Logger}, - web, App, HttpServer, +use axum::{ + routing::{get, post}, + Router, }; use clap::{Parser, Subcommand}; -use errors::FaucetError; +use http::HeaderValue; use miden_node_utils::{config::load_config, version::LongVersion}; use state::FaucetState; +use tokio::net::TcpListener; +use tower::ServiceBuilder; +use tower_http::{cors::CorsLayer, set_header::SetResponseHeaderLayer, trace::TraceLayer}; use tracing::info; use crate::{ config::FaucetConfig, - handlers::{get_metadata, get_tokens}, + errors::InitError, + handlers::{get_index, get_metadata, get_static_file, get_tokens}, }; - // CONSTANTS // ================================================================================================= @@ -56,69 +58,71 @@ pub enum Command { // MAIN // ================================================================================================= -#[actix_web::main] -async fn main() -> Result<(), FaucetError> { +#[tokio::main] +async fn main() -> Result<(), InitError> { miden_node_utils::logging::setup_logging() - .map_err(|err| FaucetError::StartError(err.to_string()))?; + .map_err(|err| InitError::FaucetFailedToStart(err.to_string()))?; let cli = Cli::parse(); match &cli.command { Command::Start { config } => { let config: FaucetConfig = load_config(config) - .map_err(|err| FaucetError::ConfigurationError(err.to_string()))?; + .map_err(|err| InitError::ConfigurationError(err.to_string()))?; let faucet_state = FaucetState::new(config.clone()).await?; info!(target: COMPONENT, %config, "Initializing server"); - info!("Server is now running on: {}", config.endpoint_url()); - - HttpServer::new(move || { - let cors = Cors::default().allow_any_origin().allow_any_method(); - App::new() - .app_data(web::Data::new(faucet_state.clone())) - .wrap(cors) - .wrap(Logger::default()) - .wrap(DefaultHeaders::new().add(("Cache-Control", "no-cache"))) - .service(get_metadata) - .service(get_tokens) - .service(actix_web_static_files::ResourceFiles::new( - "/", - static_resources::generate(), - )) - }) - .bind((config.endpoint.host, config.endpoint.port)) - .map_err(|err| FaucetError::StartError(err.to_string()))? - .run() - .await - .map_err(|err| FaucetError::StartError(err.to_string()))?; + let app = Router::new() + .route("/", get(get_index)) + .route("/get_metadata", get(get_metadata)) + .route("/get_tokens", post(get_tokens)) + .route("/*path", get(get_static_file)) + .layer( + ServiceBuilder::new() + .layer(TraceLayer::new_for_http()) + .layer(SetResponseHeaderLayer::if_not_present( + http::header::CACHE_CONTROL, + HeaderValue::from_static("no-cache"), + )) + .layer( + CorsLayer::new() + .allow_origin(tower_http::cors::Any) + .allow_methods(tower_http::cors::Any), + ), + ) + .with_state(faucet_state); + + let listener = TcpListener::bind((config.endpoint.host.as_str(), config.endpoint.port)) + .await + .map_err(|err| InitError::FaucetFailedToStart(err.to_string()))?; + + info!(target: COMPONENT, endpoint = %config.endpoint, "Server started"); + + axum::serve(listener, app).await.unwrap(); }, Command::Init { config_path } => { let current_dir = std::env::current_dir().map_err(|err| { - FaucetError::ConfigurationError(format!("failed to open current directory: {err}")) + InitError::ConfigurationError(format!("failed to open current directory: {err}")) })?; - let mut config_file_path = current_dir.clone(); - config_file_path.push(config_path); - + let config_file_path = current_dir.join(config_path); let config = FaucetConfig::default(); let config_as_toml_string = toml::to_string(&config).map_err(|err| { - FaucetError::ConfigurationError(format!( - "Failed to serialize default config: {err}" - )) + InitError::ConfigurationError(format!("Failed to serialize default config: {err}")) })?; let mut file_handle = File::options().write(true).create_new(true).open(&config_file_path).map_err( - |err| FaucetError::ConfigurationError(format!("Error opening the file: {err}")), + |err| InitError::ConfigurationError(format!("Error opening the file: {err}")), )?; file_handle.write(config_as_toml_string.as_bytes()).map_err(|err| { - FaucetError::ConfigurationError(format!("Error writing to file: {err}")) + InitError::ConfigurationError(format!("Error writing to file: {err}")) })?; - println!("Config file successfully created at: {:?}", config_file_path); + println!("Config file successfully created at: {config_file_path:?}"); }, } diff --git a/bin/faucet/src/state.rs b/bin/faucet/src/state.rs index c94175caf..898a5e7bd 100644 --- a/bin/faucet/src/state.rs +++ b/bin/faucet/src/state.rs @@ -1,11 +1,13 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; -use async_mutex::Mutex; use miden_objects::accounts::AccountId; +use static_files::Resource; +use tokio::sync::Mutex; use tracing::info; -use crate::{client::FaucetClient, config::FaucetConfig, errors::FaucetError}; - +use crate::{ + client::FaucetClient, config::FaucetConfig, errors::InitError, static_resources, COMPONENT, +}; // FAUCET STATE // ================================================================================================ @@ -18,15 +20,18 @@ pub struct FaucetState { pub id: AccountId, pub client: Arc>, pub config: FaucetConfig, + pub static_files: Arc>, } impl FaucetState { - pub async fn new(config: FaucetConfig) -> Result { + pub async fn new(config: FaucetConfig) -> Result { let client = FaucetClient::new(config.clone()).await?; let id = client.get_faucet_id(); let client = Arc::new(Mutex::new(client)); - info!("Faucet initialization successful, account id: {}", id); + let static_files = Arc::new(static_resources::generate()); + + info!(target: COMPONENT, account_id = %id, "Faucet initialization successful"); - Ok(FaucetState { client, id, config }) + Ok(FaucetState { client, id, config, static_files }) } } From 0e352bd94c4a42659d69789b4299737b35e06d0a Mon Sep 17 00:00:00 2001 From: Andrey Khmuro Date: Mon, 14 Oct 2024 19:17:30 +0300 Subject: [PATCH 2/9] `BlockWitness`: pass inputs to the VM through the advice provider (#516) --- CHANGELOG.md | 3 +- .../prover/asm/block_kernel.masm | 224 ++++++++++++------ .../src/block_builder/prover/block_witness.rs | 147 ++++++------ 3 files changed, 227 insertions(+), 147 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9bd903ba..37ded380a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,11 @@ - Optimized state synchronizations by removing unnecessary fetching and parsing of note details (#462). - [BREAKING] Changed `GetAccountDetailsResponse` field to `details` (#481). - Improve `--version` by adding build metadata (#495). -- [BREAKING] Introduced additional limits for note/account number (#503). +- [BREAKING] Introduced additional limits for note/account number (#503). - [BREAKING] Removed support for basic wallets in genesis creation (#510). - Added `GetAccountProofs` endpoint (#506). - Migrated faucet from actix-web to axum (#511). +- Changed the `BlockWitness` to pass the inputs to the VM using only advice provider (#516). ## 0.5.1 (2024-09-12) diff --git a/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm b/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm index 023f2c39a..48139646b 100644 --- a/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm +++ b/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm @@ -13,154 +13,228 @@ const.CHAIN_MMR_PTR=1000 #! Compute the account root #! -#! Stack: [num_accounts_updated, OLD_ACCOUNT_ROOT, -#! NEW_ACCOUNT_HASH_0, account_id_0, ... , NEW_ACCOUNT_HASH_n, account_id_n] -#! Output: [NEW_ACCOUNT_ROOT] +#! Inputs: +#! Operand stack: [] +#! Advice stack: [num_accounts_updated, OLD_ACCOUNT_ROOT, [NEW_ACCOUNT_HASH_i, account_id_i]] +#! Outputs: +#! Operand stack: [NEW_ACCOUNT_ROOT] proc.compute_account_root - dup neq.0 - # => [0 or 1, num_accounts_updated, OLD_ACCOUNT_ROOT, - # NEW_ACCOUNT_HASH_0, account_id_0, ... , NEW_ACCOUNT_HASH_n, account_id_n] + # move the number of updated accounts and an old account root to the operand stack + adv_push.5 + # OS => [OLD_ACCOUNT_ROOT, num_accounts_updated] + # AS => [[NEW_ACCOUNT_HASH_i, account_id_i]] + + # assess if we should loop + dup.4 neq.0 + # OS => [flag, OLD_ACCOUNT_ROOT, num_accounts_updated] + # AS => [[NEW_ACCOUNT_HASH_i, account_id_i]] while.true - # stack: [counter, ROOT_0, ..., NEW_ACCOUNT_HASH_i, account_id_i , ...] + # num_accounts_updated here serves as a counter, so rename it accordingly + # old account root will be updated in each iteration, so rename it to the ROOT_i + # OS => [ROOT_i, counter] + # AS => [[NEW_ACCOUNT_HASH_i, account_id_i]] - # Move counter down for next iteration - movdn.9 - # => [ROOT_i, NEW_ACCOUNT_HASH_i, account_id_i, counter, ...] + # move the account hash to the operand stack and move it below the root + adv_push.4 swapw + # OS => [ROOT_i, NEW_ACCOUNT_HASH_i, counter] + # AS => [account_id_i, [NEW_ACCOUNT_HASH_{i+1}, account_id_{i+1}]] - # Prepare stack for `mtree_set` - movup.8 push.ACCOUNT_TREE_DEPTH - # => [account_tree_depth, account_id_i, ROOT_i, NEW_ACCOUNT_HASH_i, counter, ...] + # move the account id to the operand stack, push the account tree depth + adv_push.1 push.ACCOUNT_TREE_DEPTH + # OS => [account_tree_depth, account_id_i, ROOT_i, NEW_ACCOUNT_HASH_i, counter] + # AS => [[NEW_ACCOUNT_HASH_{i+1}, account_id_{i+1}]] # set new value in SMT mtree_set dropw - # => [ROOT_{i+1}, counter, ...] + # OS => [ROOT_{i+1}, counter] + # AS => [[NEW_ACCOUNT_HASH_{i+1}, account_id_{i+1}]] # loop counter - movup.4 sub.1 dup neq.0 - # => [0 or 1, counter-1, ROOT_{i+1}, ...] + movup.4 sub.1 dup movdn.5 neq.0 + # OS => [flag, ROOT_{i+1}, counter] + # AS => [[NEW_ACCOUNT_HASH_{i+1}, account_id_{i+1}]] end - drop - # => [ROOT_{n-1}] + # drop the counter + movup.4 drop + # OS => [ROOT_{n-1}] + # AS => [] end #! Compute the note root. #! -#! Each batch contains a tree of depth 10 for its created notes. The block's created notes tree is created -#! by aggregating up to 2^6 tree roots coming from the batches contained in the block. +#! Each batch contains a tree of depth 10 for its created notes. The block's created notes tree is +#! created by aggregating up to 2^6 tree roots coming from the batches contained in the block. #! -#! `SMT_EMPTY_ROOT` must be `E16`, the root of the empty tree of depth 16. If less than 2^6 batches are -#! contained in the block, `E10` is used as the padding value; this is derived from the fact that -#! `SMT_EMPTY_ROOT` is `E16`, and that our tree has depth 6. +#! `SMT_EMPTY_ROOT` must be `E16`, the root of the empty tree of depth 16. If less than 2^6 batches +#! are contained in the block, `E10` is used as the padding value; this is derived from the fact +#! that `SMT_EMPTY_ROOT` is `E16`, and that our tree has depth 6. #! -#! Stack: [num_notes_updated, SMT_EMPTY_ROOT, -#! batch_note_root_idx_0, BATCH_NOTE_TREE_ROOT_0, -#! ... , -#! batch_note_root_idx_{n-1}, BATCH_NOTE_TREE_ROOT_{n-1}] -#! Output: [NOTES_ROOT] +#! Inputs: +#! Operand stack: [] +#! Advice stack: [num_notes_updated, SMT_EMPTY_ROOT, [BATCH_NOTE_TREE_ROOT_i, batch_note_root_idx_i]] +#! Outputs: +#! Operand stack: [NOTES_ROOT] proc.compute_note_root + # move the number of updated notes and empty root to the operand stack + adv_push.5 + # OS => [SMT_EMPTY_ROOT, num_notes_updated] + # AS => [[BATCH_NOTE_TREE_ROOT_i, batch_note_root_idx_i]] + # assess if we should loop - dup neq.0 - #=> [0 or 1, num_notes_updated, SMT_EMPTY_ROOT, ... ] + dup.4 neq.0 + # OS => [flag, SMT_EMPTY_ROOT, num_notes_updated] + # AS => [[BATCH_NOTE_TREE_ROOT_i, batch_note_root_idx_i]] while.true - #=> [note_roots_left_to_update, ROOT_i, batch_note_root_idx_i, BATCH_NOTE_TREE_ROOT_i, ... ] + # num_notes_updated here serves as a counter, so rename it accordingly + # empty root will be updated in each iteration, so rename it to the ROOT_i + # OS => [ROOT_i, counter] + # AS => [[BATCH_NOTE_TREE_ROOT_i, batch_note_root_idx_i]] - # Move counter down for next iteration - movdn.9 - #=> [ROOT_i, batch_note_root_idx_i, BATCH_NOTE_TREE_ROOT_i, note_roots_left_to_update, ... ] + # move the batch note tree root to the operand stack and move it below the root + adv_push.4 swapw + # OS => [ROOT_i, BATCH_NOTE_TREE_ROOT_i, counter] + # AS => [batch_note_root_idx_i, [BATCH_NOTE_TREE_ROOT_{i+1}, batch_note_root_idx_{i+1}]] - # Prepare stack for mtree_set - movup.4 push.BLOCK_NOTES_BATCH_TREE_DEPTH - #=> [depth=batch_tree_depth, batch_note_root_idx_i, ROOT_i, - # BATCH_NOTE_TREE_ROOT_i, note_roots_left_to_update, ... ] + # move the batch note root index to the operand stack, push the block notes batch tree depth + adv_push.1 push.BLOCK_NOTES_BATCH_TREE_DEPTH + # OS => [batch_tree_depth, batch_note_root_idx_i, ROOT_i, BATCH_NOTE_TREE_ROOT_i, counter] + # AS => [[BATCH_NOTE_TREE_ROOT_{i+1}, batch_note_root_idx_{i+1}]] + # set new value in SMT mtree_set dropw - #=> [ROOT_{i+1}, note_roots_left_to_update, ... ] - + # OS => [ROOT_{i+1}, counter] + # AS => [[BATCH_NOTE_TREE_ROOT_{i+1}, batch_note_root_idx_{i+1}]] + # loop counter - movup.4 sub.1 dup neq.0 - #=> [0 or 1, note_roots_left_to_update - 1, ROOT_{i+1}, ... ] + movup.4 sub.1 dup movdn.5 neq.0 + # OS => [flag, ROOT_{i+1}, counter] + # AS => [[BATCH_NOTE_TREE_ROOT_{i+1}, batch_note_root_idx_{i+1}]] end - drop - # => [ROOT_{n-1}] + # drop the counter + movup.4 drop + # OS => [ROOT_{n-1}] + # AS => [] end -#! Stack: [num_produced_nullifiers, OLD_NULLIFIER_ROOT, NULLIFIER_VALUE, -#! NULLIFIER_0, ..., NULLIFIER_n] -#! Output: [NULLIFIER_ROOT] +#! Compute the nullifier root. +#! +#! Inputs: +#! Operand stack: [] +#! Advice stack: [num_produced_nullifiers, OLD_NULLIFIER_ROOT, NULLIFIER_VALUE, [NULLIFIER_i]] +#! Outputs: +#! Operand stack: [NULLIFIER_ROOT] proc.compute_nullifier_root + # move the number of produced nullifiers, old root and nullifier value to the operand stack; + # move nullifier value below the root + adv_push.9 swapw + # OS => [OLD_NULLIFIER_ROOT, NULLIFIER_VALUE, num_produced_nullifiers] + # AS => [[NULLIFIER_i]] + # assess if we should loop - dup neq.0 - #=> [0 or 1, num_produced_nullifiers, OLD_NULLIFIER_ROOT, NULLIFIER_VALUE, NULLIFIER_0, ..., NULLIFIER_n ] + dup.8 neq.0 + # OS => [flag, OLD_NULLIFIER_ROOT, NULLIFIER_VALUE, num_produced_nullifiers] + # AS => [[NULLIFIER_i]] while.true - #=> [num_nullifiers_left_to_update, ROOT_i, NULLIFIER_VALUE, NULLIFIER_i, ... ] + # num_produced_nullifiers here serves as a counter, so rename it accordingly + # old nullifier root will be updated in each iteration, so rename it to the ROOT_i + # OS => [ROOT_i, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_i]] + + # move the nullifier hash to the operand stack + adv_push.4 + # OS => [NULLIFIER_i, ROOT_i, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_{i+1}]] - # Prepare stack for `smt::set` - movdn.12 movupw.2 dupw.2 - #=> [NULLIFIER_VALUE, NULLIFIER_i, ROOT_i, NULLIFIER_VALUE, num_nullifiers_left_to_update, ... ] + # dup the nullifier value + dupw.2 + # OS => [NULLIFIER_VALUE, NULLIFIER_i, ROOT_i, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_{i+1}]] exec.smt::set - #=> [OLD_VALUE, ROOT_{i+1}, NULLIFIER_VALUE, num_nullifiers_left_to_update, ... ] + # OS => [OLD_VALUE, ROOT_{i+1}, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_{i+1}]] # Check that OLD_VALUE == 0 (i.e. that nullifier was indeed not previously produced) assertz assertz assertz assertz - #=> [ROOT_{i+1}, NULLIFIER_VALUE, num_nullifiers_left_to_update, ... ] + # OS => [ROOT_{i+1}, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_{i+1}]] # loop counter - movup.8 sub.1 dup neq.0 - #=> [0 or 1, num_nullifiers_left_to_update - 1, ROOT_{i+1}, NULLIFIER_VALUE, ... ] + movup.8 sub.1 dup movdn.9 neq.0 + # OS => [flag, ROOT_{i+1}, NULLIFIER_VALUE, counter] + # AS => [[NULLIFIER_{i+1}]] end - #=> [0, ROOT_{n-1}, NULLIFIER_VALUE ] - drop swapw dropw - # => [ROOT_{n-1}] + # drop the counter and the nullifier value + swapw dropw movup.4 drop + # OS => [ROOT_{n-1}] + # AS => [] end #! Compute the chain MMR root #! -#! Stack: [ PREV_CHAIN_MMR_HASH, PREV_BLOCK_HASH_TO_INSERT ] -#! Advice map: PREV_CHAIN_MMR_HASH -> NUM_LEAVES || peak_0 || .. || peak_{n-1} || -#! -#! Output: [ CHAIN_MMR_ROOT ] +#! Inputs: +#! Operand stack: [] +#! Advice stack: [PREV_BLOCK_HASH_TO_INSERT, PREV_CHAIN_MMR_HASH] +#! Advice map: { +#! PREV_CHAIN_MMR_HASH: [NUM_LEAVES, [peak_i], ] +#! } +#! Outputs: +#! Operand stack: [CHAIN_MMR_ROOT] proc.compute_chain_mmr_root + # move the previous block hash and chain MMR hash to the operand stack + adv_push.8 + # OS => [PREV_CHAIN_MMR_HASH, PREV_BLOCK_HASH_TO_INSERT] + # AS => [] + + # push chain MMR pointer to the operand stack push.CHAIN_MMR_PTR movdn.4 - # => [ PREV_CHAIN_MMR_HASH, chain_mmr_ptr, PREV_BLOCK_HASH_TO_INSERT ] + # OS => [PREV_CHAIN_MMR_HASH, chain_mmr_ptr, PREV_BLOCK_HASH_TO_INSERT] # load the chain MMR (as of previous block) at memory location CHAIN_MMR_PTR exec.mmr::unpack - # => [ PREV_BLOCK_HASH_TO_INSERT ] + # OS => [PREV_BLOCK_HASH_TO_INSERT] + # push chain MMR pointer to the operand stack push.CHAIN_MMR_PTR movdn.4 - # => [ PREV_BLOCK_HASH_TO_INSERT, chain_mmr_ptr ] + # OS => [PREV_BLOCK_HASH_TO_INSERT, chain_mmr_ptr] # add PREV_BLOCK_HASH_TO_INSERT to chain MMR exec.mmr::add - # => [ ] + # OS => [] # Compute new MMR root push.CHAIN_MMR_PTR exec.mmr::pack - # => [ CHAIN_MMR_ROOT ] + # OS => [CHAIN_MMR_ROOT] end -# Stack: [, , , ] +#! Inputs: +#! Operand stack: [] +#! Advice stack: [, , , ] +#! Advice map: { +#! PREV_CHAIN_MMR_HASH: [NUM_LEAVES, [peak_i], ] +#! } +#! Outputs: +#! Operand stack: [ACCOUNT_ROOT, NOTE_ROOT, NULLIFIER_ROOT, CHAIN_MMR_ROOT] begin exec.compute_account_root mem_storew.0 dropw # => [, , ] exec.compute_note_root mem_storew.1 dropw - # => [ , ] + # => [, ] exec.compute_nullifier_root mem_storew.2 dropw - # => [ ] + # => [] exec.compute_chain_mmr_root - # => [ CHAIN_MMR_ROOT ] + # => [CHAIN_MMR_ROOT] # Load output on stack padw mem_loadw.2 padw mem_loadw.1 padw mem_loadw.0 - #=> [ ACCOUNT_ROOT, NOTE_ROOT, NULLIFIER_ROOT, CHAIN_MMR_ROOT ] -end \ No newline at end of file + # => [ACCOUNT_ROOT, NOTE_ROOT, NULLIFIER_ROOT, CHAIN_MMR_ROOT] +end diff --git a/crates/block-producer/src/block_builder/prover/block_witness.rs b/crates/block-producer/src/block_builder/prover/block_witness.rs index 9bbe473c8..0b4f06567 100644 --- a/crates/block-producer/src/block_builder/prover/block_witness.rs +++ b/crates/block-producer/src/block_builder/prover/block_witness.rs @@ -136,10 +136,9 @@ impl BlockWitness { pub(super) fn into_program_inputs( self, ) -> Result<(AdviceInputs, StackInputs), BlockProverError> { - let stack_inputs = self.build_stack_inputs(); let advice_inputs = self.build_advice_inputs()?; - Ok((advice_inputs, stack_inputs)) + Ok((advice_inputs, StackInputs::default())) } /// Returns an iterator over all transactions which affected accounts in the block with @@ -178,84 +177,88 @@ impl BlockWitness { } } - /// Builds the stack inputs to the block kernel - fn build_stack_inputs(&self) -> StackInputs { - // Note: `StackInputs::new()` reverses the input vector, so we need to construct the stack - // from the bottom to the top - let mut stack_inputs = Vec::new(); - - // Chain MMR stack inputs - { - stack_inputs.extend(self.prev_header.hash()); - stack_inputs.extend(self.chain_peaks.hash_peaks()); - } - - // Nullifiers stack inputs - { - let num_produced_nullifiers: Felt = (self.produced_nullifiers.len() as u64) - .try_into() - .expect("nullifiers number is greater than or equal to the field modulus"); + /// Builds the advice inputs to the block kernel + fn build_advice_inputs(self) -> Result { + let advice_stack = { + let mut advice_stack = Vec::new(); + + // add account stack inputs to the advice stack + { + let mut account_data = Vec::new(); + let mut num_accounts_updated: u64 = 0; + for (idx, (account_id, account_update)) in self.updated_accounts.iter().enumerate() + { + account_data.extend(account_update.final_state_hash); + account_data.push((*account_id).into()); + + let idx = u64::try_from(idx).expect("can't be more than 2^64 - 1 accounts"); + num_accounts_updated = idx + 1; + } + + // append number of accounts updated + advice_stack.push(num_accounts_updated.try_into().expect( + "updated accounts number is greater than or equal to the field modulus", + )); + + // append initial account root + advice_stack.extend(self.prev_header.account_root()); + + // append the updated accounts data + advice_stack.extend(account_data); + } - for nullifier in self.produced_nullifiers.keys() { - stack_inputs.extend(nullifier.inner()); + // add notes stack inputs to the advice stack + { + // append the number of updated notes + advice_stack + .push(Felt::try_from(self.batch_created_notes_roots.len() as u64).expect( + "notes roots number is greater than or equal to the field modulus", + )); + + // append the empty root + let empty_root = EmptySubtreeRoots::entry(BLOCK_NOTE_TREE_DEPTH, 0); + advice_stack.extend(*empty_root); + + for (batch_index, batch_created_notes_root) in self.batch_created_notes_roots.iter() + { + advice_stack.extend(batch_created_notes_root.iter()); + + let batch_index = Felt::try_from(*batch_index as u64) + .expect("batch index is greater than or equal to the field modulus"); + advice_stack.push(batch_index); + } } - // append nullifier value (`[block_num, 0, 0, 0]`) - let block_num = self.prev_header.block_num() + 1; - stack_inputs.extend([block_num.into(), ZERO, ZERO, ZERO]); + // Nullifiers stack inputs + { + let num_produced_nullifiers: Felt = (self.produced_nullifiers.len() as u64) + .try_into() + .expect("nullifiers number is greater than or equal to the field modulus"); - // append initial nullifier root - stack_inputs.extend(self.prev_header.nullifier_root()); + // append number of nullifiers + advice_stack.push(num_produced_nullifiers); - // append number of nullifiers - stack_inputs.push(num_produced_nullifiers); - } + // append initial nullifier root + advice_stack.extend(self.prev_header.nullifier_root()); - // Notes stack inputs - { - for (batch_index, batch_created_notes_root) in self.batch_created_notes_roots.iter() { - stack_inputs.extend(batch_created_notes_root.iter()); + // append nullifier value (`[block_num, 0, 0, 0]`) + let block_num = self.prev_header.block_num() + 1; + advice_stack.extend([block_num.into(), ZERO, ZERO, ZERO]); - let batch_index = Felt::try_from(*batch_index as u64) - .expect("batch index is greater than or equal to the field modulus"); - stack_inputs.push(batch_index); + for nullifier in self.produced_nullifiers.keys() { + advice_stack.extend(nullifier.inner()); + } } - let empty_root = EmptySubtreeRoots::entry(BLOCK_NOTE_TREE_DEPTH, 0); - stack_inputs.extend(*empty_root); - stack_inputs.push( - Felt::try_from(self.batch_created_notes_roots.len() as u64) - .expect("notes roots number is greater than or equal to the field modulus"), - ); - } - - // Account stack inputs - let mut num_accounts_updated: u64 = 0; - for (idx, (account_id, account_update)) in self.updated_accounts.iter().enumerate() { - stack_inputs.push((*account_id).into()); - stack_inputs.extend(account_update.final_state_hash); - - let idx = u64::try_from(idx).expect("can't be more than 2^64 - 1 accounts"); - num_accounts_updated = idx + 1; - } - - // append initial account root - stack_inputs.extend(self.prev_header.account_root()); - - // append number of accounts updated - stack_inputs.push( - num_accounts_updated - .try_into() - .expect("updated accounts number is greater than or equal to the field modulus"), - ); + // Chain MMR stack inputs + { + advice_stack.extend(self.prev_header.hash()); + advice_stack.extend(self.chain_peaks.hash_peaks()); + } - // TODO: We need provide produced nullifier different way, because such big stack inputs - // will cause problem in recursive proofs - StackInputs::new(stack_inputs).expect("Stack inputs count extends max limit") - } + advice_stack + }; - /// Builds the advice inputs to the block kernel - fn build_advice_inputs(self) -> Result { let merkle_store = { let mut merkle_store = MerkleStore::default(); @@ -290,8 +293,10 @@ impl BlockWitness { .chain(std::iter::once(mmr_peaks_advice_map_key_value(&self.chain_peaks))) .collect(); - let advice_inputs = - AdviceInputs::default().with_merkle_store(merkle_store).with_map(advice_map); + let advice_inputs = AdviceInputs::default() + .with_merkle_store(merkle_store) + .with_map(advice_map) + .with_stack(advice_stack); Ok(advice_inputs) } From d9201488974d3222eb56650c126d754372602d42 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:20:19 +0500 Subject: [PATCH 3/9] feat(store): improve errors (#518) * feat: improve node errors * docs: update `CHANGELOG.md` --- CHANGELOG.md | 1 + crates/store/src/errors.rs | 16 +++++- crates/store/src/server/api.rs | 89 +++++++++++++--------------------- crates/store/src/state.rs | 4 +- 4 files changed, 51 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ded380a..88d847b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Added `GetAccountProofs` endpoint (#506). - Migrated faucet from actix-web to axum (#511). - Changed the `BlockWitness` to pass the inputs to the VM using only advice provider (#516). +- [BREAKING] Improved store API errors (return "not found" instead of "internal error" status if requested account(s) not found) (#518). ## 0.5.1 (2024-09-12) diff --git a/crates/store/src/errors.rs b/crates/store/src/errors.rs index 2666c138a..700c9d3c5 100644 --- a/crates/store/src/errors.rs +++ b/crates/store/src/errors.rs @@ -14,6 +14,7 @@ use miden_objects::{ use rusqlite::types::FromSqlError; use thiserror::Error; use tokio::sync::oneshot::error::RecvError; +use tonic::Status; use crate::types::{AccountId, BlockNumber}; @@ -60,8 +61,6 @@ pub enum DatabaseError { InteractError(String), #[error("Deserialization of BLOB data from database failed: {0}")] DeserializationError(DeserializationError), - #[error("Corrupted data: {0}")] - CorruptedData(String), #[error("Invalid Felt: {0}")] InvalidFelt(String), #[error("Block applying was broken because of closed channel on state side: {0}")] @@ -91,6 +90,19 @@ impl From for DatabaseError { } } +impl From for Status { + fn from(err: DatabaseError) -> Self { + match err { + DatabaseError::AccountNotFoundInDb(_) + | DatabaseError::AccountsNotFoundInDb(_) + | DatabaseError::AccountNotOnChain(_) + | DatabaseError::BlockNotFoundInDb(_) => Status::not_found(err.to_string()), + + _ => Status::internal(err.to_string()), + } + } +} + // INITIALIZATION ERRORS // ================================================================================================= diff --git a/crates/store/src/server/api.rs b/crates/store/src/server/api.rs index 38e4bdaf7..0018ff166 100644 --- a/crates/store/src/server/api.rs +++ b/crates/store/src/server/api.rs @@ -70,7 +70,7 @@ impl api_server::Api for StoreApi { )] async fn get_block_header_by_number( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { info!(target: COMPONENT, ?request); let request = request.into_inner(); @@ -102,7 +102,7 @@ impl api_server::Api for StoreApi { )] async fn check_nullifiers( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { // Validate the nullifiers and convert them to Digest values. Stop on first error. let request = request.into_inner(); @@ -126,7 +126,7 @@ impl api_server::Api for StoreApi { )] async fn check_nullifiers_by_prefix( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -137,8 +137,7 @@ impl api_server::Api for StoreApi { let nullifiers = self .state .check_nullifiers_by_prefix(request.prefix_len, request.nullifiers) - .await - .map_err(internal_error)? + .await? .into_iter() .map(|nullifier_info| NullifierUpdate { nullifier: Some(nullifier_info.nullifier.into()), @@ -160,7 +159,7 @@ impl api_server::Api for StoreApi { )] async fn sync_state( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -224,7 +223,7 @@ impl api_server::Api for StoreApi { )] async fn sync_notes( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -256,7 +255,7 @@ impl api_server::Api for StoreApi { )] async fn get_notes_by_id( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { info!(target: COMPONENT, ?request); @@ -270,8 +269,7 @@ impl api_server::Api for StoreApi { let notes = self .state .get_notes_by_id(note_ids) - .await - .map_err(internal_error)? + .await? .into_iter() .map(Into::into) .collect(); @@ -289,7 +287,7 @@ impl api_server::Api for StoreApi { )] async fn get_note_authentication_info( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { info!(target: COMPONENT, ?request); @@ -325,7 +323,7 @@ impl api_server::Api for StoreApi { )] async fn get_account_details( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); let account_info = self @@ -333,8 +331,7 @@ impl api_server::Api for StoreApi { .get_account_details( request.account_id.ok_or(invalid_argument("Account missing id"))?.into(), ) - .await - .map_err(internal_error)?; + .await?; Ok(Response::new(GetAccountDetailsResponse { details: Some((&account_info).into()), @@ -354,8 +351,8 @@ impl api_server::Api for StoreApi { )] async fn apply_block( &self, - request: tonic::Request, - ) -> Result, tonic::Status> { + request: Request, + ) -> Result, Status> { let request = request.into_inner(); debug!(target: COMPONENT, ?request); @@ -391,7 +388,7 @@ impl api_server::Api for StoreApi { )] async fn get_block_inputs( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -417,7 +414,7 @@ impl api_server::Api for StoreApi { )] async fn get_transaction_inputs( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -430,8 +427,7 @@ impl api_server::Api for StoreApi { let tx_inputs = self .state .get_transaction_inputs(account_id, &nullifiers, unauthenticated_notes) - .await - .map_err(internal_error)?; + .await?; let block_height = self.state.latest_block_num().await; @@ -466,13 +462,13 @@ impl api_server::Api for StoreApi { )] async fn get_block_by_number( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); debug!(target: COMPONENT, ?request); - let block = self.state.load_block(request.block_num).await.map_err(internal_error)?; + let block = self.state.load_block(request.block_num).await?; Ok(Response::new(GetBlockByNumberResponse { block })) } @@ -494,11 +490,8 @@ impl api_server::Api for StoreApi { let account_ids = convert(request.account_ids); let include_headers = request.include_headers.unwrap_or_default(); - let (block_num, infos) = self - .state - .get_account_states(account_ids, include_headers) - .await - .map_err(internal_error)?; + let (block_num, infos) = + self.state.get_account_proofs(account_ids, include_headers).await?; Ok(Response::new(GetAccountProofsResponse { block_num, @@ -515,7 +508,7 @@ impl api_server::Api for StoreApi { )] async fn get_account_state_delta( &self, - request: tonic::Request, + request: Request, ) -> Result, Status> { let request = request.into_inner(); @@ -528,8 +521,7 @@ impl api_server::Api for StoreApi { request.from_block_num, request.to_block_num, ) - .await - .map_err(internal_error)?; + .await?; Ok(Response::new(GetAccountStateDeltaResponse { delta: Some(delta.to_bytes()) })) } @@ -547,9 +539,9 @@ impl api_server::Api for StoreApi { )] async fn list_nullifiers( &self, - _request: tonic::Request, + _request: Request, ) -> Result, Status> { - let raw_nullifiers = self.state.list_nullifiers().await.map_err(internal_error)?; + let raw_nullifiers = self.state.list_nullifiers().await?; let nullifiers = raw_nullifiers .into_iter() .map(|(key, block_num)| SmtLeafEntry { @@ -570,16 +562,9 @@ impl api_server::Api for StoreApi { )] async fn list_notes( &self, - _request: tonic::Request, + _request: Request, ) -> Result, Status> { - let notes = self - .state - .list_notes() - .await - .map_err(internal_error)? - .into_iter() - .map(Into::into) - .collect(); + let notes = self.state.list_notes().await?.into_iter().map(Into::into).collect(); Ok(Response::new(ListNotesResponse { notes })) } @@ -593,16 +578,9 @@ impl api_server::Api for StoreApi { )] async fn list_accounts( &self, - _request: tonic::Request, + _request: Request, ) -> Result, Status> { - let accounts = self - .state - .list_accounts() - .await - .map_err(internal_error)? - .iter() - .map(Into::into) - .collect(); + let accounts = self.state.list_accounts().await?.iter().map(Into::into).collect(); Ok(Response::new(ListAccountsResponse { accounts })) } } @@ -610,13 +588,14 @@ impl api_server::Api for StoreApi { // UTILITIES // ================================================================================================ -/// Formats an error -fn internal_error(err: E) -> Status { - Status::internal(format!("{:?}", err)) +/// Formats an "Internal error" error +fn internal_error(err: E) -> Status { + Status::internal(err.to_string()) } -fn invalid_argument(err: E) -> Status { - Status::invalid_argument(format!("{:?}", err)) +/// Formats an "Invalid argument" error +fn invalid_argument(err: E) -> Status { + Status::invalid_argument(err.to_string()) } #[instrument(target = "miden-store", skip_all, err)] diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index 44e03425c..294f1ebcb 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -679,8 +679,8 @@ impl State { self.db.select_account(id).await } - /// Returns account states with details for public accounts. - pub async fn get_account_states( + /// Returns account proofs with optional account and storage headers. + pub async fn get_account_proofs( &self, account_ids: Vec, include_headers: bool, From b0a1721ceb8bf709242143b436407ed7e709373f Mon Sep 17 00:00:00 2001 From: igamigo Date: Wed, 23 Oct 2024 10:45:51 -0300 Subject: [PATCH 4/9] feat: Return code for FPI (#521) * feat: Return code for FPI * Rename var * CHANGELOG * Address comments * Check earlier * Address comments * Force proto rebuild * Update crates/rpc-proto/proto/responses.proto Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> * Update description * Proto rebuild * Update description --------- Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- CHANGELOG.md | 1 + crates/proto/src/generated/requests.rs | 6 +++++- crates/proto/src/generated/responses.rs | 4 ++++ crates/rpc-proto/proto/requests.proto | 5 ++++- crates/rpc-proto/proto/responses.proto | 3 +++ crates/store/src/server/api.rs | 20 ++++++++++++++++---- crates/store/src/state.rs | 14 +++++++++++--- proto/requests.proto | 5 ++++- proto/responses.proto | 3 +++ 9 files changed, 51 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88d847b05..572ed2678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v0.6.0 (TBD) +- Added `AccountCode` as part of `GetAccountProofs` endpoint response (#521). - [BREAKING] Added `kernel_root` to block header's protobuf message definitions (#496). - [BREAKING] Renamed `off-chain` and `on-chain` to `private` and `public` respectively for the account storage modes (#489). - Optimized state synchronizations by removing unnecessary fetching and parsing of note details (#462). diff --git a/crates/proto/src/generated/requests.rs b/crates/proto/src/generated/requests.rs index 34db2cb62..ee5c70caf 100644 --- a/crates/proto/src/generated/requests.rs +++ b/crates/proto/src/generated/requests.rs @@ -153,7 +153,11 @@ pub struct GetAccountProofsRequest { /// List of account IDs to get states. #[prost(message, repeated, tag = "1")] pub account_ids: ::prost::alloc::vec::Vec, + /// Account code commitments corresponding to the last-known `AccountCode` for requested + /// accounts. Responses will include only the ones that are not known to the caller. + #[prost(message, repeated, tag = "2")] + pub code_commitments: ::prost::alloc::vec::Vec, /// Optional flag to include header in the response. `false` by default. - #[prost(bool, optional, tag = "2")] + #[prost(bool, optional, tag = "3")] pub include_headers: ::core::option::Option, } diff --git a/crates/proto/src/generated/responses.rs b/crates/proto/src/generated/responses.rs index a871cbe31..b0d695bb8 100644 --- a/crates/proto/src/generated/responses.rs +++ b/crates/proto/src/generated/responses.rs @@ -227,4 +227,8 @@ pub struct AccountStateHeader { /// Values of all account storage slots (max 255). #[prost(bytes = "vec", tag = "2")] pub storage_header: ::prost::alloc::vec::Vec, + /// Account code, returned only when none of the request's code commitments match with the + /// current one. + #[prost(bytes = "vec", optional, tag = "3")] + pub account_code: ::core::option::Option<::prost::alloc::vec::Vec>, } diff --git a/crates/rpc-proto/proto/requests.proto b/crates/rpc-proto/proto/requests.proto index 9f9554b48..5751f3978 100644 --- a/crates/rpc-proto/proto/requests.proto +++ b/crates/rpc-proto/proto/requests.proto @@ -135,6 +135,9 @@ message GetAccountStateDeltaRequest { message GetAccountProofsRequest { // List of account IDs to get states. repeated account.AccountId account_ids = 1; + // Account code commitments corresponding to the last-known `AccountCode` for requested + // accounts. Responses will include only the ones that are not known to the caller. + repeated digest.Digest code_commitments = 2; // Optional flag to include header in the response. `false` by default. - optional bool include_headers = 2; + optional bool include_headers = 3; } diff --git a/crates/rpc-proto/proto/responses.proto b/crates/rpc-proto/proto/responses.proto index 7d7d00032..b586458b1 100644 --- a/crates/rpc-proto/proto/responses.proto +++ b/crates/rpc-proto/proto/responses.proto @@ -197,4 +197,7 @@ message AccountStateHeader { account.AccountHeader header = 1; // Values of all account storage slots (max 255). bytes storage_header = 2; + // Account code, returned only when none of the request's code commitments match with the + // current one. + optional bytes account_code = 3; } diff --git a/crates/store/src/server/api.rs b/crates/store/src/server/api.rs index 0018ff166..5ca4930ed 100644 --- a/crates/store/src/server/api.rs +++ b/crates/store/src/server/api.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{collections::BTreeSet, sync::Arc}; use miden_node_proto::{ convert, @@ -485,13 +485,25 @@ impl api_server::Api for StoreApi { request: Request, ) -> Result, Status> { let request = request.into_inner(); + if request.account_ids.len() > request.code_commitments.len() { + return Err(Status::invalid_argument( + "The number of code commitments should not exceed the number of requested accounts.", + )); + } debug!(target: COMPONENT, ?request); - let account_ids = convert(request.account_ids); let include_headers = request.include_headers.unwrap_or_default(); - let (block_num, infos) = - self.state.get_account_proofs(account_ids, include_headers).await?; + let account_ids: Vec = convert(request.account_ids); + let request_code_commitments: BTreeSet = try_convert(request.code_commitments) + .map_err(|err| { + Status::invalid_argument(format!("Invalid code commitment: {}", err)) + })?; + + let (block_num, infos) = self + .state + .get_account_proofs(account_ids, request_code_commitments, include_headers) + .await?; Ok(Response::new(GetAccountProofsResponse { block_num, diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index 294f1ebcb..31b8607c2 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -5,6 +5,7 @@ use std::{ collections::{BTreeMap, BTreeSet}, + ops::Not, sync::Arc, }; @@ -683,6 +684,7 @@ impl State { pub async fn get_account_proofs( &self, account_ids: Vec, + request_code_commitments: BTreeSet, include_headers: bool, ) -> Result<(BlockNumber, Vec), DatabaseError> { // Lock inner state for the whole operation. We need to hold this lock to prevent the @@ -696,8 +698,7 @@ impl State { let infos = self.db.select_accounts_by_ids(account_ids.clone()).await?; if account_ids.len() > infos.len() { - let found_ids: BTreeSet = - infos.iter().map(|info| info.summary.account_id.into()).collect(); + let found_ids = infos.iter().map(|info| info.summary.account_id.into()).collect(); return Err(DatabaseError::AccountsNotFoundInDb( BTreeSet::from_iter(account_ids).difference(&found_ids).copied().collect(), )); @@ -712,6 +713,12 @@ impl State { AccountStateHeader { header: Some(AccountHeader::from(&details).into()), storage_header: details.storage().get_header().to_bytes(), + // Only include account code if the request did not contain it + // (known by the caller) + account_code: request_code_commitments + .contains(&details.code().commitment()) + .not() + .then_some(details.code().to_bytes()), }, ) }) @@ -724,12 +731,13 @@ impl State { .map(|account_id| { let acc_leaf_idx = LeafIndex::new_max_depth(account_id); let opening = inner_state.account_tree.open(&acc_leaf_idx); + let state_header = state_headers.get(&account_id).cloned(); AccountProofsResponse { account_id: Some(account_id.into()), account_hash: Some(opening.value.into()), account_proof: Some(opening.path.into()), - state_header: state_headers.get(&account_id).cloned(), + state_header, } }) .collect(); diff --git a/proto/requests.proto b/proto/requests.proto index 9f9554b48..5751f3978 100644 --- a/proto/requests.proto +++ b/proto/requests.proto @@ -135,6 +135,9 @@ message GetAccountStateDeltaRequest { message GetAccountProofsRequest { // List of account IDs to get states. repeated account.AccountId account_ids = 1; + // Account code commitments corresponding to the last-known `AccountCode` for requested + // accounts. Responses will include only the ones that are not known to the caller. + repeated digest.Digest code_commitments = 2; // Optional flag to include header in the response. `false` by default. - optional bool include_headers = 2; + optional bool include_headers = 3; } diff --git a/proto/responses.proto b/proto/responses.proto index 7d7d00032..b586458b1 100644 --- a/proto/responses.proto +++ b/proto/responses.proto @@ -197,4 +197,7 @@ message AccountStateHeader { account.AccountHeader header = 1; // Values of all account storage slots (max 255). bytes storage_header = 2; + // Account code, returned only when none of the request's code commitments match with the + // current one. + optional bytes account_code = 3; } From 3df08adeaf8ce809023ef7e9e7e8b67baf636c48 Mon Sep 17 00:00:00 2001 From: igamigo Date: Thu, 24 Oct 2024 15:30:13 -0300 Subject: [PATCH 5/9] fix: Incorrect validation (#526) --- crates/proto/src/generated/requests.rs | 10 ++++++---- crates/rpc-proto/proto/requests.proto | 8 +++++--- crates/store/src/server/api.rs | 2 +- proto/requests.proto | 8 +++++--- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/proto/src/generated/requests.rs b/crates/proto/src/generated/requests.rs index ee5c70caf..db4d238a5 100644 --- a/crates/proto/src/generated/requests.rs +++ b/crates/proto/src/generated/requests.rs @@ -153,11 +153,13 @@ pub struct GetAccountProofsRequest { /// List of account IDs to get states. #[prost(message, repeated, tag = "1")] pub account_ids: ::prost::alloc::vec::Vec, + /// Optional flag to include header and account code in the response. `false` by default. + #[prost(bool, optional, tag = "2")] + pub include_headers: ::core::option::Option, /// Account code commitments corresponding to the last-known `AccountCode` for requested /// accounts. Responses will include only the ones that are not known to the caller. - #[prost(message, repeated, tag = "2")] + /// These are not associated with a specific account but rather, they will be matched against + /// all requested accounts. + #[prost(message, repeated, tag = "3")] pub code_commitments: ::prost::alloc::vec::Vec, - /// Optional flag to include header in the response. `false` by default. - #[prost(bool, optional, tag = "3")] - pub include_headers: ::core::option::Option, } diff --git a/crates/rpc-proto/proto/requests.proto b/crates/rpc-proto/proto/requests.proto index 5751f3978..31a0cb68e 100644 --- a/crates/rpc-proto/proto/requests.proto +++ b/crates/rpc-proto/proto/requests.proto @@ -135,9 +135,11 @@ message GetAccountStateDeltaRequest { message GetAccountProofsRequest { // List of account IDs to get states. repeated account.AccountId account_ids = 1; + // Optional flag to include header and account code in the response. `false` by default. + optional bool include_headers = 2; // Account code commitments corresponding to the last-known `AccountCode` for requested // accounts. Responses will include only the ones that are not known to the caller. - repeated digest.Digest code_commitments = 2; - // Optional flag to include header in the response. `false` by default. - optional bool include_headers = 3; + // These are not associated with a specific account but rather, they will be matched against + // all requested accounts. + repeated digest.Digest code_commitments = 3; } diff --git a/crates/store/src/server/api.rs b/crates/store/src/server/api.rs index 5ca4930ed..51cb21ef4 100644 --- a/crates/store/src/server/api.rs +++ b/crates/store/src/server/api.rs @@ -485,7 +485,7 @@ impl api_server::Api for StoreApi { request: Request, ) -> Result, Status> { let request = request.into_inner(); - if request.account_ids.len() > request.code_commitments.len() { + if request.account_ids.len() < request.code_commitments.len() { return Err(Status::invalid_argument( "The number of code commitments should not exceed the number of requested accounts.", )); diff --git a/proto/requests.proto b/proto/requests.proto index 5751f3978..31a0cb68e 100644 --- a/proto/requests.proto +++ b/proto/requests.proto @@ -135,9 +135,11 @@ message GetAccountStateDeltaRequest { message GetAccountProofsRequest { // List of account IDs to get states. repeated account.AccountId account_ids = 1; + // Optional flag to include header and account code in the response. `false` by default. + optional bool include_headers = 2; // Account code commitments corresponding to the last-known `AccountCode` for requested // accounts. Responses will include only the ones that are not known to the caller. - repeated digest.Digest code_commitments = 2; - // Optional flag to include header in the response. `false` by default. - optional bool include_headers = 3; + // These are not associated with a specific account but rather, they will be matched against + // all requested accounts. + repeated digest.Digest code_commitments = 3; } From 22d3216bd113a35c1ade3bbf53d6825f6a919b6d Mon Sep 17 00:00:00 2001 From: Andrey Khmuro Date: Mon, 28 Oct 2024 20:59:07 +0300 Subject: [PATCH 6/9] chore: migrate to `miden-vm` v0.11 (#528) --- CHANGELOG.md | 1 + Cargo.lock | 329 +++++++++--------- Cargo.toml | 10 +- Makefile | 2 +- bin/faucet/src/client.rs | 45 +-- .../prover/asm/block_kernel.masm | 4 + .../src/block_builder/prover/mod.rs | 2 +- .../src/block_builder/prover/tests.rs | 2 +- crates/block-producer/src/test_utils/block.rs | 4 +- crates/block-producer/src/test_utils/store.rs | 10 +- crates/store/src/state.rs | 29 +- rust-toolchain.toml | 2 +- 12 files changed, 223 insertions(+), 217 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 572ed2678..33f4807f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Migrated faucet from actix-web to axum (#511). - Changed the `BlockWitness` to pass the inputs to the VM using only advice provider (#516). - [BREAKING] Improved store API errors (return "not found" instead of "internal error" status if requested account(s) not found) (#518). +- [BREAKING] Migrated to v0.11 version of Miden VM (#528). ## 0.5.1 (2024-09-12) diff --git a/Cargo.lock b/Cargo.lock index e110537a5..ee1f4a6e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -70,43 +70,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "arrayref" @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -142,9 +142,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", @@ -276,9 +276,9 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags", "cexpr", @@ -345,9 +345,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -357,9 +357,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "camino" @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -466,9 +466,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -496,9 +496,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "constant_time_eq" @@ -648,18 +648,18 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", "syn", @@ -823,9 +823,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -837,9 +837,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -847,33 +847,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-sink", @@ -918,9 +918,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -940,7 +940,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.5.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -962,6 +962,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hashlink" version = "0.9.1" @@ -1025,9 +1031,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1037,9 +1043,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1071,9 +1077,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1135,12 +1141,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -1205,9 +1211,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1234,7 +1240,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "string_cache", "term", "tiny-keccak", @@ -1262,9 +1268,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" @@ -1278,9 +1284,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "a00419de735aac21d53b0de5ce2c03bd3627277cf471300f27ebc89f7d828047" [[package]] name = "libredox" @@ -1346,7 +1352,7 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "syn", ] @@ -1396,8 +1402,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miden-air" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2702f8adb96844e3521f49149f6c3d4773ecdd2a96a3169e3c025a2e3ee32b5e" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "miden-core", "miden-thiserror", @@ -1408,8 +1413,7 @@ dependencies = [ [[package]] name = "miden-assembly" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae9cef4fbafb4fe26da18574bcdbd78815857cfe1099760782701ababb076c2" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "aho-corasick", "lalrpop", @@ -1426,8 +1430,7 @@ dependencies = [ [[package]] name = "miden-core" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc3f6db878d6b56c1566cd5b832908675566d3919b9a3523d630dfb5e2f7422d" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "lock_api", "loom", @@ -1445,9 +1448,9 @@ dependencies = [ [[package]] name = "miden-crypto" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825fc5d2e4c951f45da54da2d0d23071918d966133f85dbc219694e0b9a1e141" +checksum = "1e0ca714c8242f329b9ea6f1a5bf0e93f1490f348f982e3a606d91b884254308" dependencies = [ "blake3", "cc", @@ -1502,7 +1505,7 @@ dependencies = [ [[package]] name = "miden-lib" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#9dc06d705b8f4cae86ff08a293f379c206f13421" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" dependencies = [ "miden-assembly", "miden-objects", @@ -1696,7 +1699,7 @@ dependencies = [ [[package]] name = "miden-objects" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#9dc06d705b8f4cae86ff08a293f379c206f13421" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" dependencies = [ "miden-assembly", "miden-core", @@ -1710,8 +1713,7 @@ dependencies = [ [[package]] name = "miden-processor" version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04a128e20400086c9a985f4e5702e438ba781338fb0bdf9acff16d996c640087" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "miden-air", "miden-core", @@ -1722,8 +1724,7 @@ dependencies = [ [[package]] name = "miden-prover" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "680d9203cee09b3cee6f79dc952a15f18a1eb47744ffac4f4e559d02bfcdee7a" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "miden-air", "miden-processor", @@ -1738,8 +1739,7 @@ version = "0.6.0" [[package]] name = "miden-stdlib" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41623ad4f4ea6449760f70ab8928c682c3824d735d3e330f07e3d24d1ad20bfa" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "miden-assembly", ] @@ -1767,8 +1767,10 @@ dependencies = [ [[package]] name = "miden-tx" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#9dc06d705b8f4cae86ff08a293f379c206f13421" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" dependencies = [ + "async-trait", + "miden-assembly", "miden-lib", "miden-objects", "miden-processor", @@ -1776,14 +1778,15 @@ dependencies = [ "miden-verifier", "rand", "rand_chacha", - "winter-maybe-async 0.10.0", + "regex", + "walkdir", + "winter-maybe-async 0.10.1", ] [[package]] name = "miden-verifier" version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8144a126ecb1941122e8261e85f2e8e94c0b82740bc23879c0a14263f48797" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" dependencies = [ "miden-air", "miden-core", @@ -2009,18 +2012,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "option-ext" @@ -2114,7 +2117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.6.0", ] [[package]] @@ -2128,18 +2131,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", @@ -2148,9 +2151,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2187,9 +2190,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", "syn", @@ -2197,9 +2200,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2231,7 +2234,7 @@ dependencies = [ "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -2406,9 +2409,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags", ] @@ -2426,14 +2429,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2447,13 +2450,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2464,9 +2467,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rusqlite" @@ -2524,9 +2527,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags", "errno", @@ -2537,9 +2540,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rusty-fork" @@ -2606,18 +2609,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", @@ -2626,9 +2629,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -2797,9 +2800,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -2818,11 +2821,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "target-triple" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" + [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -2874,18 +2883,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", @@ -2946,9 +2955,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -3022,7 +3031,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -3269,15 +3278,16 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.99" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207aa50d36c4be8d8c6ea829478be44a372c6a77669937bb39c698e52f1491e8" +checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4" dependencies = [ "dissimilar", "glob", "serde", "serde_derive", "serde_json", + "target-triple", "termcolor", "toml", ] @@ -3305,12 +3315,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" @@ -3456,9 +3463,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -3467,9 +3474,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -3482,9 +3489,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3492,9 +3499,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -3505,9 +3512,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "winapi" @@ -3828,9 +3835,9 @@ dependencies = [ [[package]] name = "winter-maybe-async" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77eafc7944188b941c90759b938b8377247ee6e440952a0a7c4dbde7edc4ecbb" +checksum = "be43529f43f70306437d2c2c9f9e2b3a4d39b42e86702d8d7577f2357ea32fa6" dependencies = [ "quote", "syn", diff --git a/Cargo.toml b/Cargo.toml index 656515f39..dfc3349c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ resolver = "2" [workspace.package] edition = "2021" -rust-version = "1.80" +rust-version = "1.82" version = "0.6.0" license = "MIT" authors = ["Miden contributors"] @@ -25,8 +25,8 @@ exclude = [".github/"] readme = "README.md" [workspace.dependencies] -miden-air = { version = "0.10", default-features = false } -miden-lib = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next"} +miden-air = { git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next" } +miden-lib = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } miden-node-block-producer = { path = "crates/block-producer", version = "0.6" } miden-node-faucet = { path = "bin/faucet", version = "0.6" } miden-node-proto = { path = "crates/proto", version = "0.6" } @@ -36,8 +36,8 @@ miden-node-store = { path = "crates/store", version = "0.6" } miden-node-test-macro = { path = "crates/test-macro" } miden-node-utils = { path = "crates/utils", version = "0.6" } miden-objects = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } -miden-processor = { version = "0.10" } -miden-stdlib = { version = "0.10", default-features = false } +miden-processor = { git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next" } +miden-stdlib = { git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } prost = { version = "0.13" } thiserror = { version = "1.0" } diff --git a/Makefile b/Makefile index afa1a2da9..b10ad72a9 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ BUILD_PROTO=BUILD_PROTO=1 .PHONY: clippy clippy: ## Runs Clippy with configs - cargo clippy --locked --workspace --all-targets --all-features -- -D warnings + cargo clippy --locked --workspace --all-targets --all-features -- -D warnings --allow clippy::arc_with_non_send_sync .PHONY: fix diff --git a/bin/faucet/src/client.rs b/bin/faucet/src/client.rs index d02f4a138..ae5d55a90 100644 --- a/bin/faucet/src/client.rs +++ b/bin/faucet/src/client.rs @@ -1,4 +1,7 @@ -use std::{cell::RefCell, rc::Rc, time::Duration}; +use std::{ + sync::{Arc, Mutex}, + time::Duration, +}; use miden_lib::{ accounts::faucets::create_basic_fungible_faucet, notes::create_p2id_note, @@ -45,8 +48,8 @@ pub const DISTRIBUTE_FUNGIBLE_ASSET_SCRIPT: &str = /// for the faucet. pub struct FaucetClient { rpc_api: ApiClient, - executor: TransactionExecutor>, - data_store: FaucetDataStore, + executor: TransactionExecutor, + data_store: Arc, id: AccountId, rng: RpoRandomCoin, } @@ -60,20 +63,19 @@ impl FaucetClient { initialize_faucet_client(config.clone()).await?; let (faucet_account, account_seed, secret) = build_account(config.clone())?; - let faucet_account = Rc::new(RefCell::new(faucet_account)); - let id = faucet_account.borrow().id(); + let id = faucet_account.id(); - let data_store = FaucetDataStore::new( - faucet_account.clone(), + let data_store = Arc::new(FaucetDataStore::new( + faucet_account, account_seed, root_block_header, root_chain_mmr, - ); - let authenticator = BasicAuthenticator::::new(&[( + )); + let authenticator = Arc::new(BasicAuthenticator::::new(&[( secret.public_key().into(), AuthSecretKey::RpoFalcon512(secret), - )]); - let executor = TransactionExecutor::new(data_store.clone(), Some(Rc::new(authenticator))); + )])); + let executor = TransactionExecutor::new(data_store.clone(), Some(authenticator)); let mut rng = thread_rng(); let coin_seed: [u64; 4] = rng.gen(); @@ -135,9 +137,10 @@ impl FaucetClient { let request = { let transaction_prover = LocalTransactionProver::new(ProvingOptions::default()); - let proven_transaction = transaction_prover.prove(executed_tx).map_err(|err| { - ProcessError::InternalServerError(format!("Failed to prove transaction: {err}")) - })?; + let proven_transaction = + transaction_prover.prove(executed_tx.into()).map_err(|err| { + ProcessError::InternalServerError(format!("Failed to prove transaction: {err}")) + })?; SubmitProvenTransactionRequest { transaction: proven_transaction.to_bytes(), @@ -162,9 +165,8 @@ impl FaucetClient { } } -#[derive(Clone)] pub struct FaucetDataStore { - faucet_account: Rc>, + faucet_account: Mutex, seed: Word, block_header: BlockHeader, chain_mmr: ChainMmr, @@ -175,13 +177,13 @@ pub struct FaucetDataStore { impl FaucetDataStore { pub fn new( - faucet_account: Rc>, + faucet_account: Account, seed: Word, root_block_header: BlockHeader, root_chain_mmr: ChainMmr, ) -> Self { Self { - faucet_account, + faucet_account: Mutex::new(faucet_account), seed, block_header: root_block_header, chain_mmr: root_chain_mmr, @@ -189,9 +191,10 @@ impl FaucetDataStore { } /// Updates the stored faucet account with the provided delta. - fn update_faucet_account(&mut self, delta: &AccountDelta) -> Result<(), ProcessError> { + fn update_faucet_account(&self, delta: &AccountDelta) -> Result<(), ProcessError> { self.faucet_account - .borrow_mut() + .lock() + .expect("Poisoned lock") .apply_delta(delta) .map_err(|err| ProcessError::InternalServerError(err.to_string())) } @@ -204,7 +207,7 @@ impl DataStore for FaucetDataStore { _block_ref: u32, _notes: &[NoteId], ) -> Result { - let account = self.faucet_account.borrow(); + let account = self.faucet_account.lock().expect("Poisoned lock"); if account_id != account.id() { return Err(DataStoreError::AccountNotFound(account_id)); } diff --git a/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm b/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm index 48139646b..63e277047 100644 --- a/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm +++ b/crates/block-producer/src/block_builder/prover/asm/block_kernel.masm @@ -6,6 +6,7 @@ use.std::collections::smt use.std::collections::mmr +use.std::sys const.ACCOUNT_TREE_DEPTH=64 const.BLOCK_NOTES_BATCH_TREE_DEPTH=6 @@ -237,4 +238,7 @@ begin # Load output on stack padw mem_loadw.2 padw mem_loadw.1 padw mem_loadw.0 # => [ACCOUNT_ROOT, NOTE_ROOT, NULLIFIER_ROOT, CHAIN_MMR_ROOT] + + # truncate the stack + exec.sys::truncate_stack end diff --git a/crates/block-producer/src/block_builder/prover/mod.rs b/crates/block-producer/src/block_builder/prover/mod.rs index 17f7d6424..cede229eb 100644 --- a/crates/block-producer/src/block_builder/prover/mod.rs +++ b/crates/block-producer/src/block_builder/prover/mod.rs @@ -88,7 +88,7 @@ impl BlockProver { let advice_provider = MemAdviceProvider::from(advice_inputs); let mut host = DefaultHost::new(advice_provider); - host.load_mast_forest(StdLibrary::default().into()); + host.load_mast_forest(StdLibrary::default().mast_forest().clone()); host }; diff --git a/crates/block-producer/src/block_builder/prover/tests.rs b/crates/block-producer/src/block_builder/prover/tests.rs index 09f98d787..3d776ffc6 100644 --- a/crates/block-producer/src/block_builder/prover/tests.rs +++ b/crates/block-producer/src/block_builder/prover/tests.rs @@ -843,7 +843,7 @@ async fn test_compute_chain_mmr_root_mmr_17_peaks() { mmr.add(Digest::default()); } - assert_eq!(mmr.peaks(mmr.forest()).unwrap().peaks().len(), 17); + assert_eq!(mmr.peaks().peaks().len(), 17); mmr }; diff --git a/crates/block-producer/src/test_utils/block.rs b/crates/block-producer/src/test_utils/block.rs index a8678eea6..71d15f7e6 100644 --- a/crates/block-producer/src/test_utils/block.rs +++ b/crates/block-producer/src/test_utils/block.rs @@ -49,7 +49,7 @@ pub async fn build_expected_block_header( store_chain_mmr.add(last_block_header.hash()); - store_chain_mmr.peaks(store_chain_mmr.forest()).unwrap().hash_peaks() + store_chain_mmr.peaks().hash_peaks() }; let note_created_smt = note_created_smt_from_note_batches(block_output_notes(batches.iter())); @@ -157,7 +157,7 @@ impl MockBlockBuilder { 0, self.last_block_header.hash(), self.last_block_header.block_num() + 1, - self.store_chain_mmr.peaks(self.store_chain_mmr.forest()).unwrap().hash_peaks(), + self.store_chain_mmr.peaks().hash_peaks(), self.store_accounts.root(), Digest::default(), note_created_smt_from_note_batches(created_notes.iter()).root(), diff --git a/crates/block-producer/src/test_utils/store.rs b/crates/block-producer/src/test_utils/store.rs index bf1e89328..f1fb7fef4 100644 --- a/crates/block-producer/src/test_utils/store.rs +++ b/crates/block-producer/src/test_utils/store.rs @@ -121,7 +121,7 @@ impl MockStoreSuccessBuilder { 0, Digest::default(), block_num, - chain_mmr.peaks(chain_mmr.forest()).unwrap().hash_peaks(), + chain_mmr.peaks().hash_peaks(), accounts_smt.root(), nullifiers_smt.root(), note_root, @@ -301,7 +301,7 @@ impl Store for MockStoreSuccess { let chain_peaks = { let locked_chain_mmr = self.chain_mmr.read().await; - locked_chain_mmr.peaks(locked_chain_mmr.forest()).unwrap() + locked_chain_mmr.peaks() }; let accounts = { @@ -329,15 +329,13 @@ impl Store for MockStoreSuccess { *locked_headers.iter().max_by_key(|(block_num, _)| *block_num).unwrap().1; let locked_chain_mmr = self.chain_mmr.read().await; - let mmr_forest = locked_chain_mmr.forest(); let chain_length = latest_header.block_num(); let block_proofs = note_proofs .values() .map(|note_proof| { let block_num = note_proof.location().block_num(); let block_header = *locked_headers.get(&block_num).unwrap(); - let mmr_path = - locked_chain_mmr.open(block_num as usize, mmr_forest).unwrap().merkle_path; + let mmr_path = locked_chain_mmr.open(block_num as usize).unwrap().merkle_path; BlockInclusionProof { block_header, mmr_path, chain_length } }) @@ -376,7 +374,7 @@ impl Store for MockStoreSuccess { let block_num = note_proof.location().block_num(); let block_header = *locked_headers.get(&block_num).unwrap(); let mmr_path = locked_chain_mmr - .open(block_num as usize, latest_header.block_num() as usize) + .open_at(block_num as usize, latest_header.block_num() as usize) .unwrap() .merkle_path; diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index 31b8607c2..169684777 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -232,12 +232,7 @@ impl State { let mut chain_mmr = inner.chain_mmr.clone(); // new_block.chain_root must be equal to the chain MMR root prior to the update - let peaks = chain_mmr.peaks(chain_mmr.forest()).map_err(|error| { - ApplyBlockError::FailedToGetMmrPeaksForForest { - forest: chain_mmr.forest(), - error, - } - })?; + let peaks = chain_mmr.peaks(); if peaks.hash_peaks() != header.chain_root() { return Err(ApplyBlockError::NewBlockInvalidChainRoot); } @@ -372,8 +367,7 @@ impl State { if let Some(header) = block_header { let mmr_proof = if include_mmr_proof { let inner = self.inner.read().await; - let mmr_proof = - inner.chain_mmr.open(header.block_num() as usize, inner.chain_mmr.forest())?; + let mmr_proof = inner.chain_mmr.open(header.block_num() as usize)?; Some(mmr_proof) } else { None @@ -444,7 +438,7 @@ impl State { let paths = blocks .iter() .map(|&block_num| { - let proof = state.chain_mmr.open(block_num as usize, chain_length)?.merkle_path; + let proof = state.chain_mmr.open(block_num as usize)?.merkle_path; Ok::<_, MmrError>((block_num, proof)) }) @@ -548,9 +542,7 @@ impl State { let note_sync = self.db.get_note_sync(block_num, note_tags).await?; - let mmr_proof = inner - .chain_mmr - .open(note_sync.block_header.block_num() as usize, inner.chain_mmr.forest())?; + let mmr_proof = inner.chain_mmr.open(note_sync.block_header.block_num() as usize)?; Ok((note_sync, mmr_proof)) } @@ -580,12 +572,13 @@ impl State { // using current block number gets us the peaks of the chain MMR as of one block ago; // this is done so that latest.chain_root matches the returned peaks - let chain_peaks = inner.chain_mmr.peaks(latest.block_num() as usize).map_err(|error| { - GetBlockInputsError::FailedToGetMmrPeaksForForest { - forest: latest.block_num() as usize, - error, - } - })?; + let chain_peaks = + inner.chain_mmr.peaks_at(latest.block_num() as usize).map_err(|error| { + GetBlockInputsError::FailedToGetMmrPeaksForForest { + forest: latest.block_num() as usize, + error, + } + })?; let account_states = account_ids .iter() .cloned() diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b12899f14..6ad542bbc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.80" +channel = "1.82" components = ["rustfmt", "rust-src", "clippy"] profile = "minimal" From 17a5ca1f47c8cd70f145b2f5ef075bc719bd9804 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:53:57 +0500 Subject: [PATCH 7/9] feat(node): avoid cloning in-memory data structures on `apply_block` (#532) * feat: avoid cloning in-memory data structures on `apply_block` * docs: update `CHANGELOG.md` * chore: update `miden-crypto` dependency Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> * Update CHANGELOG.md Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> * chore: update `Cargo.lock` * refactor: address review comments * fix: prevent inconsistent in-memory and DB states * refactor: address review comments --------- Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> --- CHANGELOG.md | 1 + crates/store/src/nullifier_tree.rs | 45 ++++---- crates/store/src/state.rs | 161 +++++++++++++++-------------- 3 files changed, 110 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33f4807f2..1b1d07d9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Changed the `BlockWitness` to pass the inputs to the VM using only advice provider (#516). - [BREAKING] Improved store API errors (return "not found" instead of "internal error" status if requested account(s) not found) (#518). - [BREAKING] Migrated to v0.11 version of Miden VM (#528). +- Reduce cloning in the store's `apply_block` (#532). ## 0.5.1 (2024-09-12) diff --git a/crates/store/src/nullifier_tree.rs b/crates/store/src/nullifier_tree.rs index b5f3c542d..04f868015 100644 --- a/crates/store/src/nullifier_tree.rs +++ b/crates/store/src/nullifier_tree.rs @@ -1,7 +1,7 @@ use miden_objects::{ crypto::{ hash::rpo::RpoDigest, - merkle::{Smt, SmtProof}, + merkle::{MutationSet, Smt, SmtProof, SMT_DEPTH}, }, notes::Nullifier, Felt, FieldElement, Word, @@ -27,7 +27,7 @@ impl NullifierTree { Ok(Self(inner)) } - /// Get SMT root. + /// Returns the root of the nullifier SMT. pub fn root(&self) -> RpoDigest { self.0.root() } @@ -37,26 +37,6 @@ impl NullifierTree { self.0.open(&nullifier.inner()) } - /// Inserts block number in which nullifier was consumed. - pub fn insert( - &mut self, - nullifier: &Nullifier, - block_num: BlockNumber, - ) -> Result<(), NullifierTreeError> { - let key = nullifier.inner(); - let prev_value = self.0.get_value(&key); - if prev_value != Smt::EMPTY_VALUE { - return Err(NullifierTreeError::NullifierAlreadyExists { - nullifier: *nullifier, - block_num: Self::leaf_value_to_block_num(prev_value), - }); - } - - self.0.insert(key, Self::block_num_to_leaf_value(block_num)); - - Ok(()) - } - /// Returns block number stored for the given nullifier or `None` if the nullifier wasn't /// consumed. pub fn get_block_num(&self, nullifier: &Nullifier) -> Option { @@ -68,6 +48,27 @@ impl NullifierTree { Some(Self::leaf_value_to_block_num(value)) } + /// Computes mutations for the nullifier SMT. + pub fn compute_mutations( + &self, + kv_pairs: impl IntoIterator, + ) -> MutationSet { + self.0.compute_mutations(kv_pairs.into_iter().map(|(nullifier, block_num)| { + (nullifier.inner(), Self::block_num_to_leaf_value(block_num)) + })) + } + + /// Applies mutations to the nullifier SMT. + pub fn apply_mutations( + &mut self, + mutations: MutationSet, + ) -> Result<(), NullifierTreeError> { + self.0.apply_mutations(mutations).map_err(Into::into) + } + + // HELPER FUNCTIONS + // -------------------------------------------------------------------------------------------- + /// Returns the nullifier's leaf value in the SMT by its block number. fn block_num_to_leaf_value(block: BlockNumber) -> Word { [Felt::from(block), Felt::ZERO, Felt::ZERO, Felt::ZERO] diff --git a/crates/store/src/state.rs b/crates/store/src/state.rs index 169684777..3ff4c4197 100644 --- a/crates/store/src/state.rs +++ b/crates/store/src/state.rs @@ -203,15 +203,21 @@ impl State { // block store. Thus, such block should be considered as block candidates, but not // finalized blocks. So we should check for the latest block when getting block from // the store. - let store = self.block_store.clone(); + let store = Arc::clone(&self.block_store); let block_save_task = tokio::spawn(async move { store.save_block(block_num, &block_data).await }); - // scope to read in-memory data, validate the request, and compute intermediary values - let (account_tree, chain_mmr, nullifier_tree, notes) = { + // scope to read in-memory data, compute mutations required for updating account + // and nullifier trees, and validate the request + let ( + nullifier_tree_old_root, + nullifier_tree_update, + account_tree_old_root, + account_tree_update, + ) = { let inner = self.inner.read().await; - let span = info_span!(target: COMPONENT, "update_in_memory_structs").entered(); + let _span = info_span!(target: COMPONENT, "update_in_memory_structs").entered(); // nullifiers can be produced only once let duplicate_nullifiers: Vec<_> = block @@ -224,83 +230,72 @@ impl State { return Err(ApplyBlockError::DuplicatedNullifiers(duplicate_nullifiers)); } - // update the in-memory data structures and compute the new block header. Important, the - // structures are not yet committed + // compute updates for the in-memory data structures - // update chain MMR - let chain_mmr = { - let mut chain_mmr = inner.chain_mmr.clone(); - - // new_block.chain_root must be equal to the chain MMR root prior to the update - let peaks = chain_mmr.peaks(); - if peaks.hash_peaks() != header.chain_root() { - return Err(ApplyBlockError::NewBlockInvalidChainRoot); - } - - chain_mmr.add(block_hash); - chain_mmr - }; - - // update nullifier tree - let nullifier_tree = { - let mut nullifier_tree = inner.nullifier_tree.clone(); - for nullifier in block.nullifiers() { - nullifier_tree - .insert(nullifier, block_num) - .map_err(ApplyBlockError::FailedToUpdateNullifierTree)?; - } + // new_block.chain_root must be equal to the chain MMR root prior to the update + let peaks = inner.chain_mmr.peaks(); + if peaks.hash_peaks() != header.chain_root() { + return Err(ApplyBlockError::NewBlockInvalidChainRoot); + } - if nullifier_tree.root() != header.nullifier_root() { - return Err(ApplyBlockError::NewBlockInvalidNullifierRoot); - } - nullifier_tree - }; + // compute update for nullifier tree + let nullifier_tree_update = inner.nullifier_tree.compute_mutations( + block.nullifiers().iter().map(|nullifier| (*nullifier, block_num)), + ); - // update account tree - let mut account_tree = inner.account_tree.clone(); - for update in block.updated_accounts() { - account_tree.insert( - LeafIndex::new_max_depth(update.account_id().into()), - update.new_state_hash().into(), - ); + if nullifier_tree_update.root() != header.nullifier_root() { + return Err(ApplyBlockError::NewBlockInvalidNullifierRoot); } - if account_tree.root() != header.account_root() { + // compute update for account tree + let account_tree_update = inner.account_tree.compute_mutations( + block.updated_accounts().iter().map(|update| { + ( + LeafIndex::new_max_depth(update.account_id().into()), + update.new_state_hash().into(), + ) + }), + ); + + if account_tree_update.root() != header.account_root() { return Err(ApplyBlockError::NewBlockInvalidAccountRoot); } - // build note tree - let note_tree = block.build_note_tree(); - if note_tree.root() != header.note_root() { - return Err(ApplyBlockError::NewBlockInvalidNoteRoot); - } + ( + inner.nullifier_tree.root(), + nullifier_tree_update, + inner.account_tree.root(), + account_tree_update, + ) + }; - drop(span); - - let notes = block - .notes() - .map(|(note_index, note)| { - let details = match note { - OutputNote::Full(note) => Some(note.to_bytes()), - OutputNote::Header(_) => None, - note => return Err(ApplyBlockError::InvalidOutputNoteType(note.clone())), - }; - - let merkle_path = note_tree.get_note_path(note_index); - - Ok(NoteRecord { - block_num, - note_index, - note_id: note.id().into(), - metadata: *note.metadata(), - details, - merkle_path, - }) - }) - .collect::, ApplyBlockError>>()?; + // build note tree + let note_tree = block.build_note_tree(); + if note_tree.root() != header.note_root() { + return Err(ApplyBlockError::NewBlockInvalidNoteRoot); + } - (account_tree, chain_mmr, nullifier_tree, notes) - }; + let notes = block + .notes() + .map(|(note_index, note)| { + let details = match note { + OutputNote::Full(note) => Some(note.to_bytes()), + OutputNote::Header(_) => None, + note => return Err(ApplyBlockError::InvalidOutputNoteType(note.clone())), + }; + + let merkle_path = note_tree.get_note_path(note_index); + + Ok(NoteRecord { + block_num, + note_index, + note_id: note.id().into(), + metadata: *note.metadata(), + details, + merkle_path, + }) + }) + .collect::, ApplyBlockError>>()?; // Signals the transaction is ready to be committed, and the write lock can be acquired let (allow_acquire, acquired_allowed) = oneshot::channel::<()>(); @@ -311,7 +306,7 @@ impl State { // overlapping. Namely, the DB transaction only proceeds after this task acquires the // in-memory write lock. This requires the DB update to run concurrently, so a new task is // spawned. - let db = self.db.clone(); + let db = Arc::clone(&self.db); let db_update_task = tokio::spawn( async move { db.apply_block(allow_acquire, acquire_done, block, notes).await }, @@ -332,6 +327,16 @@ impl State { // successfully. let mut inner = self.inner.write().await; + // We need to check that neither the nullifier tree nor the account tree have changed + // while we were waiting for the DB preparation task to complete. If either of them + // did change, we do not proceed with in-memory and database updates, since it may + // lead to an inconsistent state. + if inner.nullifier_tree.root() != nullifier_tree_old_root + || inner.account_tree.root() != account_tree_old_root + { + return Err(ApplyBlockError::ConcurrentWrite); + } + // Notify the DB update task that the write lock has been acquired, so it can commit // the DB transaction let _ = inform_acquire_done.send(()); @@ -343,9 +348,15 @@ impl State { db_update_task.await??; // Update the in-memory data structures after successful commit of the DB transaction - inner.chain_mmr = chain_mmr; - inner.nullifier_tree = nullifier_tree; - inner.account_tree = account_tree; + inner + .nullifier_tree + .apply_mutations(nullifier_tree_update) + .expect("Unreachable: old nullifier tree root must be checked before this step"); + inner + .account_tree + .apply_mutations(account_tree_update) + .expect("Unreachable: old account tree root must be checked before this step"); + inner.chain_mmr.add(block_hash); } info!(%block_hash, block_num, COMPONENT, "apply_block successful"); From f5416109fce40a372128fe347de7a14801dad190 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Wed, 30 Oct 2024 23:29:39 +0500 Subject: [PATCH 8/9] fix(faucet): resume after restart (#517) * feat: improve node errors * docs: update `CHANGELOG.md` * feat: save/restore faucet state and keypair to/from files * feat: make faucet account public, request account state on submission error * feat: introduce `ClientError` * fix: update config * fix: save new faucet state to in-memory store after getting from the server * fix: remove `macros` feature from axum dependency * docs: update `CHANGELOG.md` * docs: add comment for `seed` field Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> * fix: log message Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> * refactor: address review comments * refactor: initial changes * refactor: impl Send and Sync for FaucetDataStore * chore: update changelog * refactor: remove unnecessary async, add warning ignore to makefile * refactor: update genesis generation, read faucet account from `faucet.mac`, request faucet state on initialization * feat: faucet account creation * fix: handling of account not found error * refactor: use Arc and Mutex * chore: removed unneeded cast * fix: lint * docs: update CHANGELOG.md * fix: compilation errors * docs: add `TODO` for incorrect and unsafe `Send` implementation * refactor: small refactoring * refactor: address review comments * docs: update `README.md` for faucet * docs: improve instructions and clarifications in faucet's `README.md` --------- Co-authored-by: Mirko <48352201+Mirko-von-Leipzig@users.noreply.github.com> Co-authored-by: Andrey Co-authored-by: Bobbin Threadbare --- .github/workflows/deploy_package.yml | 2 +- CHANGELOG.md | 1 + Cargo.lock | 3 + Cargo.toml | 1 + bin/faucet/Cargo.toml | 5 +- bin/faucet/README.md | 26 ++- bin/faucet/src/client.rs | 286 +++++++++++------------- bin/faucet/src/config.rs | 31 +-- bin/faucet/src/errors.rs | 41 ++-- bin/faucet/src/handlers.rs | 31 ++- bin/faucet/src/main.rs | 116 +++++++--- bin/faucet/src/state.rs | 9 +- bin/faucet/src/store.rs | 73 ++++++ bin/node/Cargo.toml | 1 + bin/node/src/commands/genesis/inputs.rs | 6 - bin/node/src/commands/genesis/mod.rs | 85 +++---- bin/node/src/main.rs | 7 +- config/genesis.toml | 2 - config/miden-faucet.toml | 6 +- crates/utils/Cargo.toml | 1 + crates/utils/src/crypto.rs | 13 ++ crates/utils/src/lib.rs | 1 + 22 files changed, 437 insertions(+), 310 deletions(-) create mode 100644 bin/faucet/src/store.rs create mode 100644 crates/utils/src/crypto.rs diff --git a/.github/workflows/deploy_package.yml b/.github/workflows/deploy_package.yml index 53530896b..d2de0c2ba 100644 --- a/.github/workflows/deploy_package.yml +++ b/.github/workflows/deploy_package.yml @@ -117,7 +117,7 @@ jobs: sudo chown -R miden /opt/miden; \ sudo /usr/bin/miden-node init -c /etc/miden/miden-node.toml -g /opt/miden/miden-node/genesis.toml; \ sudo /usr/bin/miden-node make-genesis -i /opt/miden/miden-node/genesis.toml -o /opt/miden/miden-node/genesis.dat --force; \ - sudo /usr/bin/miden-faucet init -c /opt/miden/miden-faucet/miden-faucet.toml + sudo /usr/bin/miden-faucet init -c /opt/miden/miden-faucet/miden-faucet.toml -f /opt/miden/miden-node/accounts/faucet.mac - name: Start miden node service uses: ./.github/actions/ssm_execute diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b1d07d9b..ed2ecf837 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - [BREAKING] Improved store API errors (return "not found" instead of "internal error" status if requested account(s) not found) (#518). - [BREAKING] Migrated to v0.11 version of Miden VM (#528). - Reduce cloning in the store's `apply_block` (#532). +- [BREAKING] Changed faucet storage type in the genesis to public. Using faucet from the genesis for faucet web app. Added support for faucet restarting without blockchain restarting (#517). ## 0.5.1 (2024-09-12) diff --git a/Cargo.lock b/Cargo.lock index ee1f4a6e2..67049c24b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1469,6 +1469,7 @@ dependencies = [ name = "miden-faucet" version = "0.6.0" dependencies = [ + "anyhow", "axum", "clap", "figment", @@ -1568,6 +1569,7 @@ dependencies = [ "miden-node-store", "miden-node-utils", "miden-objects", + "rand", "rand_chacha", "serde", "tokio", @@ -1686,6 +1688,7 @@ dependencies = [ "figment", "itertools 0.12.1", "miden-objects", + "rand", "serde", "thiserror", "tonic", diff --git a/Cargo.toml b/Cargo.toml index dfc3349c8..9e0d53b99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ miden-processor = { git = "https://github.com/0xPolygonMiden/miden-vm.git", bran miden-stdlib = { git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } prost = { version = "0.13" } +rand = { version = "0.8" } thiserror = { version = "1.0" } tokio = { version = "1.40", features = ["rt-multi-thread"] } tokio-stream = { version = "0.1" } diff --git a/bin/faucet/Cargo.toml b/bin/faucet/Cargo.toml index fc03a81ad..7d299e3e2 100644 --- a/bin/faucet/Cargo.toml +++ b/bin/faucet/Cargo.toml @@ -17,6 +17,7 @@ repository.workspace = true testing = ["miden-objects/testing", "miden-lib/testing"] [dependencies] +anyhow = "1.0" axum = { version = "0.7", features = ["tokio"] } clap = { version = "4.5", features = ["derive", "string"] } figment = { version = "0.10", features = ["toml", "env"] } @@ -28,12 +29,12 @@ miden-node-utils = { workspace = true } miden-objects = { workspace = true , features = ["concurrent"] } miden-tx = { workspace = true, features = ["concurrent"] } mime = "0.3" -rand = { version = "0.8" } +rand = { workspace = true } rand_chacha = "0.3" serde = { version = "1.0", features = ["derive"] } static-files = "0.2" thiserror = { workspace = true } -tokio = { workspace = true } +tokio = { workspace = true, features = ["fs"] } toml = { version = "0.8" } tonic = { workspace = true } tower = "0.5" diff --git a/bin/faucet/README.md b/bin/faucet/README.md index 2d9fe8edb..2d7b15e55 100644 --- a/bin/faucet/README.md +++ b/bin/faucet/README.md @@ -2,8 +2,12 @@ This crate contains a binary for running a Miden rollup faucet. -## Running the faucet -1. Run a local node, for example using the docker image. From the "miden-node" repo root run the following commands: +## Running the faucet in testing mode + +> [!TIP] +> Miden account generation uses a proof-of-work puzzle to prevent DoS attacks. These puzzles can be quite expensive, especially for test purposes. You can lower the difficulty of the puzzle by appending `--features testing` to the `cargo install ..` invocation. + +1. Run a local node with the "testing" feature, for example using the docker image. From the "miden-node" repo root run the following commands: ```bash make docker-build-node make docker-run-node @@ -14,12 +18,24 @@ make docker-run-node make install-faucet-testing ``` -3. Create the default faucet configuration file: +3. [Optional] Create faucet account (skip this step if you want to use an account from the genesis). This will generate authentication keypair and generate and write public faucet account data with its keypair into the file specified in `output-path`: + +```bash +miden-faucet create-faucet-account \ + --output-path \ + --token-symbol POL \ + --decimals 9 \ + --max-supply 1000000000 +``` +> [!TIP] +> This account will not be created on chain yet, creation on chain will happen on the first minting transaction. + +4. Create the default faucet configuration file. Specify the path to the faucet account file created on the previous step in the `-f` flag (if you want to use an account from the genesis, specify the path to the `faucet.mac` file generated by the [make-genesis](../../README.md#setup) command of the Miden node): ```bash -miden-faucet init +miden-faucet init -f ``` -4. Start the faucet server: +5. Start the faucet server: ```bash miden-faucet start ``` diff --git a/bin/faucet/src/client.rs b/bin/faucet/src/client.rs index ae5d55a90..ce76a37ed 100644 --- a/bin/faucet/src/client.rs +++ b/bin/faucet/src/client.rs @@ -1,41 +1,39 @@ -use std::{ - sync::{Arc, Mutex}, - time::Duration, -}; +use std::{sync::Arc, time::Duration}; -use miden_lib::{ - accounts::faucets::create_basic_fungible_faucet, notes::create_p2id_note, - transaction::TransactionKernel, AuthScheme, -}; +use anyhow::Context; +use miden_lib::{notes::create_p2id_note, transaction::TransactionKernel}; use miden_node_proto::generated::{ - requests::{GetBlockHeaderByNumberRequest, SubmitProvenTransactionRequest}, + requests::{ + GetAccountDetailsRequest, GetBlockHeaderByNumberRequest, SubmitProvenTransactionRequest, + }, rpc::api_client::ApiClient, }; use miden_objects::{ - accounts::{Account, AccountDelta, AccountId, AccountStorageMode, AuthSecretKey}, - assets::{FungibleAsset, TokenSymbol}, + accounts::{Account, AccountData, AccountId, AuthSecretKey}, + assets::FungibleAsset, crypto::{ - dsa::rpo_falcon512::SecretKey, merkle::{MmrPeaks, PartialMmr}, rand::RpoRandomCoin, }, - notes::{Note, NoteId, NoteType}, - transaction::{ChainMmr, ExecutedTransaction, InputNotes, TransactionArgs, TransactionScript}, + notes::{Note, NoteType}, + transaction::{ChainMmr, ExecutedTransaction, TransactionArgs, TransactionScript}, + utils::Deserializable, vm::AdviceMap, - BlockHeader, Felt, Word, + BlockHeader, Felt, }; use miden_tx::{ - auth::BasicAuthenticator, utils::Serializable, DataStore, DataStoreError, - LocalTransactionProver, ProvingOptions, TransactionExecutor, TransactionInputs, - TransactionProver, + auth::BasicAuthenticator, utils::Serializable, LocalTransactionProver, ProvingOptions, + TransactionExecutor, TransactionProver, }; -use rand::{rngs::StdRng, thread_rng, Rng}; -use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; +use rand::{random, rngs::StdRng}; use tonic::transport::Channel; +use tracing::info; use crate::{ config::FaucetConfig, - errors::{InitError, ProcessError}, + errors::{ClientError, ImplError}, + store::FaucetDataStore, + COMPONENT, }; pub const DISTRIBUTE_FUNGIBLE_ASSET_SCRIPT: &str = @@ -54,31 +52,68 @@ pub struct FaucetClient { rng: RpoRandomCoin, } +// TODO: Remove this once https://github.com/0xPolygonMiden/miden-base/issues/909 is resolved unsafe impl Send for FaucetClient {} -unsafe impl Sync for FaucetClient {} impl FaucetClient { - pub async fn new(config: FaucetConfig) -> Result { - let (rpc_api, root_block_header, root_chain_mmr) = - initialize_faucet_client(config.clone()).await?; - - let (faucet_account, account_seed, secret) = build_account(config.clone())?; - let id = faucet_account.id(); + /// Fetches the latest faucet account state from the node and creates a new faucet client. + /// + /// # Note + /// If the faucet account is not found on chain, it will be created on submission of the first + /// minting transaction. + pub async fn new(config: &FaucetConfig) -> Result { + let (mut rpc_api, root_block_header, root_chain_mmr) = + initialize_faucet_client(config).await?; + + let faucet_account_data = AccountData::read(&config.faucet_account_path) + .context("Failed to load faucet account from file")?; + + let id = faucet_account_data.account.id(); + + info!(target: COMPONENT, "Requesting account state from the node..."); + let faucet_account = match request_account_state(&mut rpc_api, id).await { + Ok(account) => { + info!( + target: COMPONENT, + hash = %account.hash(), + nonce = %account.nonce(), + "Received faucet account state from the node", + ); + + account + }, + + Err(err) => match err { + ClientError::RequestError(status) if status.code() == tonic::Code::NotFound => { + info!(target: COMPONENT, "Faucet account not found in the node"); + + faucet_account_data.account + }, + _ => { + return Err(err); + }, + }, + }; let data_store = Arc::new(FaucetDataStore::new( faucet_account, - account_seed, + faucet_account_data.account_seed, root_block_header, root_chain_mmr, )); - let authenticator = Arc::new(BasicAuthenticator::::new(&[( - secret.public_key().into(), - AuthSecretKey::RpoFalcon512(secret), - )])); - let executor = TransactionExecutor::new(data_store.clone(), Some(authenticator)); - - let mut rng = thread_rng(); - let coin_seed: [u64; 4] = rng.gen(); + + let public_key = match &faucet_account_data.auth_secret_key { + AuthSecretKey::RpoFalcon512(secret) => secret.public_key(), + }; + + let authenticator = BasicAuthenticator::::new(&[( + public_key.into(), + faucet_account_data.auth_secret_key, + )]); + + let executor = TransactionExecutor::new(data_store.clone(), Some(Arc::new(authenticator))); + + let coin_seed: [u64; 4] = random(); let rng = RpoRandomCoin::new(coin_seed.map(Felt::new)); Ok(Self { data_store, rpc_api, executor, id, rng }) @@ -92,9 +127,9 @@ impl FaucetClient { target_account_id: AccountId, is_private_note: bool, asset_amount: u64, - ) -> Result<(ExecutedTransaction, Note), ProcessError> { - let asset = FungibleAsset::new(self.id, asset_amount) - .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; + ) -> Result<(ExecutedTransaction, Note), ClientError> { + let asset = + FungibleAsset::new(self.id, asset_amount).context("Failed to create fungible asset")?; let note_type = if is_private_note { NoteType::Private @@ -110,16 +145,14 @@ impl FaucetClient { Default::default(), &mut self.rng, ) - .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; + .context("Failed to create P2ID note")?; let transaction_args = build_transaction_arguments(&output_note, note_type, asset)?; let executed_tx = self .executor .execute_transaction(self.id, 0, &[], transaction_args) - .map_err(|err| { - ProcessError::InternalServerError(format!("Failed to execute transaction: {err}")) - })?; + .context("Failed to execute transaction")?; Ok((executed_tx, output_note)) } @@ -128,19 +161,16 @@ impl FaucetClient { pub async fn prove_and_submit_transaction( &mut self, executed_tx: ExecutedTransaction, - ) -> Result { - let delta = executed_tx.account_delta().clone(); - + ) -> Result { // Prepare request with proven transaction. // This is needed to be in a separated code block in order to release reference to avoid // borrow checker error. let request = { let transaction_prover = LocalTransactionProver::new(ProvingOptions::default()); - let proven_transaction = - transaction_prover.prove(executed_tx.into()).map_err(|err| { - ProcessError::InternalServerError(format!("Failed to prove transaction: {err}")) - })?; + let proven_transaction = transaction_prover + .prove(executed_tx.into()) + .context("Failed to prove transaction")?; SubmitProvenTransactionRequest { transaction: proven_transaction.to_bytes(), @@ -151,137 +181,50 @@ impl FaucetClient { .rpc_api .submit_proven_transaction(request) .await - .map_err(|err| ProcessError::InternalServerError(err.to_string()))?; - - self.data_store.update_faucet_account(&delta).map_err(|err| { - ProcessError::InternalServerError(format!("Failed to update account: {err}")) - })?; + .context("Failed to submit proven transaction")?; Ok(response.into_inner().block_height) } - pub fn get_faucet_id(&self) -> AccountId { - self.id + /// Returns a reference to the data store. + pub fn data_store(&self) -> &FaucetDataStore { + &self.data_store } -} - -pub struct FaucetDataStore { - faucet_account: Mutex, - seed: Word, - block_header: BlockHeader, - chain_mmr: ChainMmr, -} -// FAUCET DATA STORE -// ================================================================================================ - -impl FaucetDataStore { - pub fn new( - faucet_account: Account, - seed: Word, - root_block_header: BlockHeader, - root_chain_mmr: ChainMmr, - ) -> Self { - Self { - faucet_account: Mutex::new(faucet_account), - seed, - block_header: root_block_header, - chain_mmr: root_chain_mmr, - } - } - - /// Updates the stored faucet account with the provided delta. - fn update_faucet_account(&self, delta: &AccountDelta) -> Result<(), ProcessError> { - self.faucet_account - .lock() - .expect("Poisoned lock") - .apply_delta(delta) - .map_err(|err| ProcessError::InternalServerError(err.to_string())) - } -} - -impl DataStore for FaucetDataStore { - fn get_transaction_inputs( - &self, - account_id: AccountId, - _block_ref: u32, - _notes: &[NoteId], - ) -> Result { - let account = self.faucet_account.lock().expect("Poisoned lock"); - if account_id != account.id() { - return Err(DataStoreError::AccountNotFound(account_id)); - } - - let empty_input_notes = - InputNotes::new(Vec::new()).map_err(DataStoreError::InvalidTransactionInput)?; - - TransactionInputs::new( - account.clone(), - account.is_new().then_some(self.seed), - self.block_header, - self.chain_mmr.clone(), - empty_input_notes, - ) - .map_err(DataStoreError::InvalidTransactionInput) + /// Returns the id of the faucet account. + pub fn get_faucet_id(&self) -> AccountId { + self.id } } // HELPER FUNCTIONS // ================================================================================================ -/// Builds a new faucet account with the provided configuration. -/// -/// Returns the created account, its seed, and the secret key used to sign transactions. -fn build_account(config: FaucetConfig) -> Result<(Account, Word, SecretKey), InitError> { - let token_symbol = TokenSymbol::new(config.token_symbol.as_str()) - .map_err(|err| InitError::AccountCreationError(err.to_string()))?; - - let seed: [u8; 32] = [0; 32]; - - // Instantiate keypair and auth scheme - let mut rng = ChaCha20Rng::from_seed(seed); - let secret = SecretKey::with_rng(&mut rng); - let auth_scheme = AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }; - - let (faucet_account, account_seed) = create_basic_fungible_faucet( - seed, - token_symbol, - config.decimals, - Felt::try_from(config.max_supply) - .map_err(|err| InitError::AccountCreationError(err.to_string()))?, - AccountStorageMode::Private, - auth_scheme, - ) - .map_err(|err| InitError::AccountCreationError(err.to_string()))?; - - Ok((faucet_account, account_seed, secret)) -} - /// Initializes the faucet client by connecting to the node and fetching the root block header. pub async fn initialize_faucet_client( - config: FaucetConfig, -) -> Result<(ApiClient, BlockHeader, ChainMmr), InitError> { + config: &FaucetConfig, +) -> Result<(ApiClient, BlockHeader, ChainMmr), ClientError> { let endpoint = tonic::transport::Endpoint::try_from(config.node_url.clone()) - .map_err(|_| InitError::ClientInitFailed("Failed to connect to node.".to_string()))? + .context("Failed to parse node URL from configuration file")? .timeout(Duration::from_millis(config.timeout_ms)); - let mut rpc_api = ApiClient::connect(endpoint) - .await - .map_err(|err| InitError::ClientInitFailed(err.to_string()))?; + let mut rpc_api = + ApiClient::connect(endpoint).await.context("Failed to connect to the node")?; let request = GetBlockHeaderByNumberRequest { block_num: Some(0), - include_mmr_proof: Some(true), + include_mmr_proof: None, }; let response = rpc_api .get_block_header_by_number(request) .await - .map_err(|err| InitError::ClientInitFailed(format!("Failed to get block header: {err}")))?; - let root_block_header = response.into_inner().block_header.unwrap(); + .context("Failed to get block header")?; + let root_block_header = response + .into_inner() + .block_header + .context("Missing root block header in response")?; - let root_block_header: BlockHeader = root_block_header.try_into().map_err(|err| { - InitError::ClientInitFailed(format!("Failed to parse block header: {err}")) - })?; + let root_block_header = root_block_header.try_into().context("Failed to parse block header")?; let root_chain_mmr = ChainMmr::new( PartialMmr::from_peaks( @@ -294,12 +237,35 @@ pub async fn initialize_faucet_client( Ok((rpc_api, root_block_header, root_chain_mmr)) } +/// Requests account state from the node. +/// +/// The account is expected to be public, otherwise, the error is returned. +async fn request_account_state( + rpc_api: &mut ApiClient, + account_id: AccountId, +) -> Result { + let account_info = rpc_api + .get_account_details(GetAccountDetailsRequest { account_id: Some(account_id.into()) }) + .await? + .into_inner() + .details + .context("Account info field is empty")?; + + let faucet_account_state_bytes = + account_info.details.context("Account details field is empty")?; + + Account::read_from_bytes(&faucet_account_state_bytes) + .map_err(ImplError) + .context("Failed to deserialize faucet account") + .map_err(Into::into) +} + /// Builds transaction arguments for the mint transaction. fn build_transaction_arguments( output_note: &Note, note_type: NoteType, asset: FungibleAsset, -) -> Result { +) -> Result { let recipient = output_note .recipient() .digest() @@ -321,9 +287,7 @@ fn build_transaction_arguments( .replace("{execution_hint}", &Felt::new(execution_hint).to_string()); let script = TransactionScript::compile(script, vec![], TransactionKernel::assembler()) - .map_err(|err| { - ProcessError::InternalServerError(format!("Failed to compile script: {err}")) - })?; + .context("Failed to compile script")?; let mut transaction_args = TransactionArgs::new(Some(script), None, AdviceMap::new()); transaction_args.extend_expected_output_notes(vec![output_note.clone()]); diff --git a/bin/faucet/src/config.rs b/bin/faucet/src/config.rs index 1e443585a..d61fe5cbf 100644 --- a/bin/faucet/src/config.rs +++ b/bin/faucet/src/config.rs @@ -1,4 +1,7 @@ -use std::fmt::{Display, Formatter}; +use std::{ + fmt::{Display, Formatter}, + path::PathBuf, +}; use miden_node_utils::config::{Endpoint, DEFAULT_FAUCET_SERVER_PORT, DEFAULT_NODE_RPC_PORT}; use serde::{Deserialize, Serialize}; @@ -6,30 +9,32 @@ use serde::{Deserialize, Serialize}; // Faucet config // ================================================================================================ +/// Default path to the faucet account file +pub const DEFAULT_FAUCET_ACCOUNT_PATH: &str = "accounts/faucet.mac"; + +/// Default timeout for RPC requests +pub const DEFAULT_RPC_TIMEOUT_MS: u64 = 10000; + #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct FaucetConfig { /// Endpoint of the faucet pub endpoint: Endpoint, - /// Node RPC gRPC endpoint in the format `http://[:]`. + /// Node RPC gRPC endpoint in the format `http://[:]` pub node_url: String, /// Timeout for RPC requests in milliseconds pub timeout_ms: u64, /// Possible options on the amount of asset that should be dispersed on each faucet request pub asset_amount_options: Vec, - /// Token symbol of the generated fungible asset - pub token_symbol: String, - /// Number of decimals of the generated fungible asset - pub decimals: u8, - /// Maximum supply of the generated fungible asset - pub max_supply: u64, + /// Path to the faucet account file + pub faucet_account_path: PathBuf, } impl Display for FaucetConfig { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( - "{{ endpoint: \"{}\", asset_amount_options: {:?}, token_symbol: {}, decimals: {}, max_supply: {} }}", - self.endpoint, self.asset_amount_options, self.token_symbol, self.decimals, self.max_supply + "{{ endpoint: \"{}\", node_url: \"{}\", timeout_ms: \"{}\", asset_amount_options: {:?}, faucet_account_path: \"{}\" }}", + self.endpoint, self.node_url, self.timeout_ms, self.asset_amount_options, self.faucet_account_path.display() )) } } @@ -39,11 +44,9 @@ impl Default for FaucetConfig { Self { endpoint: Endpoint::localhost(DEFAULT_FAUCET_SERVER_PORT), node_url: Endpoint::localhost(DEFAULT_NODE_RPC_PORT).to_string(), - timeout_ms: 10000, + timeout_ms: DEFAULT_RPC_TIMEOUT_MS, asset_amount_options: vec![100, 500, 1000], - token_symbol: "POL".to_string(), - decimals: 8, - max_supply: 1000000, + faucet_account_path: DEFAULT_FAUCET_ACCOUNT_PATH.into(), } } } diff --git a/bin/faucet/src/errors.rs b/bin/faucet/src/errors.rs index 50777c719..c87054133 100644 --- a/bin/faucet/src/errors.rs +++ b/bin/faucet/src/errors.rs @@ -1,56 +1,61 @@ +use std::fmt::{Debug, Display}; + use axum::{ http::{header, StatusCode}, response::{IntoResponse, Response}, }; use thiserror::Error; +/// Wrapper for implementing `Error` trait for errors, which do not implement it, like +/// [miden_objects::crypto::utils::DeserializationError] and other error types from `miden-base`. #[derive(Debug, Error)] -pub enum InitError { - #[error("Failed to start faucet: {0}")] - FaucetFailedToStart(String), - - #[error("Failed to initialize client: {0}")] - ClientInitFailed(String), +#[error("{0}")] +pub struct ImplError(pub E); - #[error("Failed to configure faucet: {0}")] - ConfigurationError(String), +#[derive(Debug, Error)] +pub enum ClientError { + #[error("Request error: {0}")] + RequestError(#[from] tonic::Status), - #[error("Failed to create Miden account: {0}")] - AccountCreationError(String), + #[error("Client error: {0:#}")] + Other(#[from] anyhow::Error), } #[derive(Debug, Error)] -pub enum ProcessError { +pub enum HandlerError { + #[error("Node client error: {0}")] + ClientError(#[from] ClientError), + + #[error("Server has encountered an internal error: {0:#}")] + Internal(#[from] anyhow::Error), + #[error("Client has submitted a bad request: {0}")] BadRequest(String), - #[error("Server has encountered an internal error: {0}")] - InternalServerError(String), - #[error("Page not found: {0}")] NotFound(String), } -impl ProcessError { +impl HandlerError { fn status_code(&self) -> StatusCode { match *self { Self::BadRequest(_) => StatusCode::BAD_REQUEST, Self::NotFound(_) => StatusCode::NOT_FOUND, - Self::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::ClientError(_) | Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR, } } fn message(&self) -> String { match self { Self::BadRequest(msg) => msg, - Self::InternalServerError(_) => "Error processing request", + Self::ClientError(_) | Self::Internal(_) => "Error processing request", Self::NotFound(msg) => msg, } .to_string() } } -impl IntoResponse for ProcessError { +impl IntoResponse for HandlerError { fn into_response(self) -> Response { ( self.status_code(), diff --git a/bin/faucet/src/handlers.rs b/bin/faucet/src/handlers.rs index 5e51e4fda..764f997d6 100644 --- a/bin/faucet/src/handlers.rs +++ b/bin/faucet/src/handlers.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use axum::{ extract::{Path, State}, http::{Response, StatusCode}, @@ -15,7 +16,7 @@ use serde::{Deserialize, Serialize}; use tonic::body; use tracing::info; -use crate::{errors::ProcessError, state::FaucetState, COMPONENT}; +use crate::{errors::HandlerError, state::FaucetState, COMPONENT}; #[derive(Deserialize)] pub struct FaucetRequest { @@ -44,7 +45,7 @@ pub async fn get_metadata( pub async fn get_tokens( State(state): State, Json(req): Json, -) -> Result { +) -> Result { info!( target: COMPONENT, account_id = %req.account_id, @@ -55,14 +56,14 @@ pub async fn get_tokens( // Check that the amount is in the asset amount options if !state.config.asset_amount_options.contains(&req.asset_amount) { - return Err(ProcessError::BadRequest("Invalid asset amount".to_string())); + return Err(HandlerError::BadRequest("Invalid asset amount".to_string())); } let mut client = state.client.lock().await; // Receive and hex user account id let target_account_id = AccountId::from_hex(req.account_id.as_str()) - .map_err(|err| ProcessError::BadRequest(err.to_string()))?; + .map_err(|err| HandlerError::BadRequest(err.to_string()))?; // Execute transaction info!(target: COMPONENT, "Executing mint transaction for account."); @@ -72,16 +73,24 @@ pub async fn get_tokens( req.asset_amount, )?; + let mut faucet_account = client.data_store().faucet_account(); + faucet_account + .apply_delta(executed_tx.account_delta()) + .context("Failed to apply faucet account delta")?; + // Run transaction prover & send transaction to node info!(target: COMPONENT, "Proving and submitting transaction."); let block_height = client.prove_and_submit_transaction(executed_tx).await?; + // Update data store with the new faucet state + client.data_store().update_faucet_state(faucet_account).await?; + let note_id: NoteId = created_note.id(); let note_details = NoteDetails::new(created_note.assets().clone(), created_note.recipient().clone()); let note_tag = NoteTag::from_account_id(target_account_id, NoteExecutionMode::Local) - .expect("failed to build note tag for local execution"); + .context("failed to build note tag for local execution")?; // Serialize note into bytes let bytes = NoteFile::NoteDetails { @@ -100,24 +109,26 @@ pub async fn get_tokens( .header(header::CONTENT_DISPOSITION, "attachment; filename=note.mno") .header("Note-Id", note_id.to_string()) .body(body::boxed(Full::from(bytes))) - .map_err(|err| ProcessError::InternalServerError(err.to_string())) + .context("Failed to build response") + .map_err(Into::into) } -pub async fn get_index(state: State) -> Result { +pub async fn get_index(state: State) -> Result { get_static_file(state, Path("index.html".to_string())).await } pub async fn get_static_file( State(state): State, Path(path): Path, -) -> Result { +) -> Result { info!(target: COMPONENT, path, "Serving static file"); - let static_file = state.static_files.get(path.as_str()).ok_or(ProcessError::NotFound(path))?; + let static_file = state.static_files.get(path.as_str()).ok_or(HandlerError::NotFound(path))?; Response::builder() .status(StatusCode::OK) .header(header::CONTENT_TYPE, static_file.mime_type) .body(body::boxed(Full::from(static_file.data))) - .map_err(|err| ProcessError::InternalServerError(err.to_string())) + .context("Failed to build response") + .map_err(Into::into) } diff --git a/bin/faucet/src/main.rs b/bin/faucet/src/main.rs index f58f9f184..a172440ad 100644 --- a/bin/faucet/src/main.rs +++ b/bin/faucet/src/main.rs @@ -3,16 +3,27 @@ mod config; mod errors; mod handlers; mod state; +mod store; -use std::{fs::File, io::Write, path::PathBuf}; +use std::path::PathBuf; +use anyhow::Context; use axum::{ routing::{get, post}, Router, }; use clap::{Parser, Subcommand}; use http::HeaderValue; -use miden_node_utils::{config::load_config, version::LongVersion}; +use miden_lib::{accounts::faucets::create_basic_fungible_faucet, AuthScheme}; +use miden_node_utils::{config::load_config, crypto::get_rpo_random_coin, version::LongVersion}; +use miden_objects::{ + accounts::{AccountData, AccountStorageMode, AuthSecretKey}, + assets::TokenSymbol, + crypto::dsa::rpo_falcon512::SecretKey, + Felt, +}; +use rand::Rng; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use state::FaucetState; use tokio::net::TcpListener; use tower::ServiceBuilder; @@ -20,10 +31,10 @@ use tower_http::{cors::CorsLayer, set_header::SetResponseHeaderLayer, trace::Tra use tracing::info; use crate::{ - config::FaucetConfig, - errors::InitError, + config::{FaucetConfig, DEFAULT_FAUCET_ACCOUNT_PATH}, handlers::{get_index, get_metadata, get_static_file, get_tokens}, }; + // CONSTANTS // ================================================================================================= @@ -48,10 +59,24 @@ pub enum Command { config: PathBuf, }, - /// Generates default configuration file for the faucet + /// Create a new public faucet account and save to the specified file + CreateFaucetAccount { + #[arg(short, long, value_name = "FILE", default_value = DEFAULT_FAUCET_ACCOUNT_PATH)] + output_path: PathBuf, + #[arg(short, long)] + token_symbol: String, + #[arg(short, long)] + decimals: u8, + #[arg(short, long)] + max_supply: u64, + }, + + /// Generate default configuration file for the faucet Init { #[arg(short, long, default_value = FAUCET_CONFIG_FILE_PATH)] config_path: String, + #[arg(short, long, default_value = DEFAULT_FAUCET_ACCOUNT_PATH)] + faucet_account_path: String, }, } @@ -59,16 +84,15 @@ pub enum Command { // ================================================================================================= #[tokio::main] -async fn main() -> Result<(), InitError> { - miden_node_utils::logging::setup_logging() - .map_err(|err| InitError::FaucetFailedToStart(err.to_string()))?; +async fn main() -> anyhow::Result<()> { + miden_node_utils::logging::setup_logging().context("Failed to initialize logging")?; let cli = Cli::parse(); match &cli.command { Command::Start { config } => { - let config: FaucetConfig = load_config(config) - .map_err(|err| InitError::ConfigurationError(err.to_string()))?; + let config: FaucetConfig = + load_config(config).context("Failed to load configuration file")?; let faucet_state = FaucetState::new(config.clone()).await?; @@ -96,31 +120,67 @@ async fn main() -> Result<(), InitError> { let listener = TcpListener::bind((config.endpoint.host.as_str(), config.endpoint.port)) .await - .map_err(|err| InitError::FaucetFailedToStart(err.to_string()))?; + .context("Failed to bind TCP listener")?; info!(target: COMPONENT, endpoint = %config.endpoint, "Server started"); axum::serve(listener, app).await.unwrap(); }, - Command::Init { config_path } => { - let current_dir = std::env::current_dir().map_err(|err| { - InitError::ConfigurationError(format!("failed to open current directory: {err}")) - })?; + + Command::CreateFaucetAccount { + output_path, + token_symbol, + decimals, + max_supply, + } => { + println!("Generating new faucet account. This may take a few minutes..."); + + let current_dir = + std::env::current_dir().context("Failed to open current directory")?; + + let mut rng = ChaCha20Rng::from_seed(rand::random()); + + let secret = SecretKey::with_rng(&mut get_rpo_random_coin(&mut rng)); + + let (account, account_seed) = create_basic_fungible_faucet( + rng.gen(), + TokenSymbol::try_from(token_symbol.as_str()) + .context("Failed to parse token symbol")?, + *decimals, + Felt::try_from(*max_supply) + .expect("max supply value is greater than or equal to the field modulus"), + AccountStorageMode::Public, + AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }, + ) + .context("Failed to create basic fungible faucet account")?; + + let account_data = + AccountData::new(account, Some(account_seed), AuthSecretKey::RpoFalcon512(secret)); + + let output_path = current_dir.join(output_path); + account_data + .write(&output_path) + .context("Failed to write account data to file")?; + + println!("Faucet account file successfully created at: {output_path:?}"); + }, + + Command::Init { config_path, faucet_account_path } => { + let current_dir = + std::env::current_dir().context("Failed to open current directory")?; let config_file_path = current_dir.join(config_path); - let config = FaucetConfig::default(); - let config_as_toml_string = toml::to_string(&config).map_err(|err| { - InitError::ConfigurationError(format!("Failed to serialize default config: {err}")) - })?; - - let mut file_handle = - File::options().write(true).create_new(true).open(&config_file_path).map_err( - |err| InitError::ConfigurationError(format!("Error opening the file: {err}")), - )?; - - file_handle.write(config_as_toml_string.as_bytes()).map_err(|err| { - InitError::ConfigurationError(format!("Error writing to file: {err}")) - })?; + + let config = FaucetConfig { + faucet_account_path: faucet_account_path.into(), + ..FaucetConfig::default() + }; + + let config_as_toml_string = + toml::to_string(&config).context("Failed to serialize default config")?; + + std::fs::write(&config_file_path, config_as_toml_string) + .context("Error writing config to file")?; println!("Config file successfully created at: {config_file_path:?}"); }, diff --git a/bin/faucet/src/state.rs b/bin/faucet/src/state.rs index 898a5e7bd..fb6940812 100644 --- a/bin/faucet/src/state.rs +++ b/bin/faucet/src/state.rs @@ -5,9 +5,8 @@ use static_files::Resource; use tokio::sync::Mutex; use tracing::info; -use crate::{ - client::FaucetClient, config::FaucetConfig, errors::InitError, static_resources, COMPONENT, -}; +use crate::{client::FaucetClient, config::FaucetConfig, static_resources, COMPONENT}; + // FAUCET STATE // ================================================================================================ @@ -24,8 +23,8 @@ pub struct FaucetState { } impl FaucetState { - pub async fn new(config: FaucetConfig) -> Result { - let client = FaucetClient::new(config.clone()).await?; + pub async fn new(config: FaucetConfig) -> anyhow::Result { + let client = FaucetClient::new(&config).await?; let id = client.get_faucet_id(); let client = Arc::new(Mutex::new(client)); let static_files = Arc::new(static_resources::generate()); diff --git a/bin/faucet/src/store.rs b/bin/faucet/src/store.rs new file mode 100644 index 000000000..02050765e --- /dev/null +++ b/bin/faucet/src/store.rs @@ -0,0 +1,73 @@ +use std::sync::Mutex; + +use miden_objects::{ + accounts::{Account, AccountId}, + notes::NoteId, + transaction::{ChainMmr, InputNotes, TransactionInputs}, + BlockHeader, Word, +}; +use miden_tx::{DataStore, DataStoreError}; + +use crate::errors::HandlerError; + +pub struct FaucetDataStore { + faucet_account: Mutex, + /// Optional initial seed used for faucet account creation. + init_seed: Option, + block_header: BlockHeader, + chain_mmr: ChainMmr, +} + +// FAUCET DATA STORE +// ================================================================================================ + +impl FaucetDataStore { + pub fn new( + faucet_account: Account, + init_seed: Option, + block_header: BlockHeader, + chain_mmr: ChainMmr, + ) -> Self { + Self { + faucet_account: Mutex::new(faucet_account), + init_seed, + block_header, + chain_mmr, + } + } + + /// Returns the stored faucet account. + pub fn faucet_account(&self) -> Account { + self.faucet_account.lock().expect("Poisoned lock").clone() + } + + /// Updates the stored faucet account with the new one. + pub async fn update_faucet_state(&self, new_faucet_state: Account) -> Result<(), HandlerError> { + *self.faucet_account.lock().expect("Poisoned lock") = new_faucet_state; + + Ok(()) + } +} + +impl DataStore for FaucetDataStore { + fn get_transaction_inputs( + &self, + account_id: AccountId, + _block_ref: u32, + _notes: &[NoteId], + ) -> Result { + let account = self.faucet_account.lock().expect("Poisoned lock"); + if account_id != account.id() { + return Err(DataStoreError::AccountNotFound(account_id)); + } + + TransactionInputs::new( + account.clone(), + account.is_new().then_some(self.init_seed).flatten(), + self.block_header, + self.chain_mmr.clone(), + InputNotes::default(), + ) + .map_err(DataStoreError::InvalidTransactionInput) + } +} diff --git a/bin/node/Cargo.toml b/bin/node/Cargo.toml index d544f285f..b855cbe64 100644 --- a/bin/node/Cargo.toml +++ b/bin/node/Cargo.toml @@ -26,6 +26,7 @@ miden-node-rpc = { workspace = true } miden-node-store = { workspace = true } miden-node-utils = { workspace = true } miden-objects = { workspace = true } +rand = { workspace = true } rand_chacha = "0.3" serde = { version = "1.0", features = ["derive"] } tokio = { workspace = true, features = ["rt-multi-thread", "net", "macros"] } diff --git a/bin/node/src/commands/genesis/inputs.rs b/bin/node/src/commands/genesis/inputs.rs index a400fc69f..2f93d1d60 100644 --- a/bin/node/src/commands/genesis/inputs.rs +++ b/bin/node/src/commands/genesis/inputs.rs @@ -23,9 +23,7 @@ pub enum AccountInput { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BasicFungibleFaucetInputs { - pub init_seed: String, pub auth_scheme: AuthSchemeInput, - pub auth_seed: String, pub token_symbol: String, pub decimals: u8, pub max_supply: u64, @@ -46,11 +44,7 @@ impl Default for GenesisInput { .expect("Current timestamp should be greater than unix epoch") .as_secs() as u32, accounts: Some(vec![AccountInput::BasicFungibleFaucet(BasicFungibleFaucetInputs { - init_seed: "0xc123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - .to_string(), auth_scheme: AuthSchemeInput::RpoFalcon512, - auth_seed: "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - .to_string(), token_symbol: "POL".to_string(), decimals: 12, max_supply: 1000000, diff --git a/bin/node/src/commands/genesis/mod.rs b/bin/node/src/commands/genesis/mod.rs index 3772b1201..8e9d7f7f3 100644 --- a/bin/node/src/commands/genesis/mod.rs +++ b/bin/node/src/commands/genesis/mod.rs @@ -7,17 +7,15 @@ use anyhow::{anyhow, bail, Context, Result}; pub use inputs::{AccountInput, AuthSchemeInput, GenesisInput}; use miden_lib::{accounts::faucets::create_basic_fungible_faucet, AuthScheme}; use miden_node_store::genesis::GenesisState; -use miden_node_utils::config::load_config; +use miden_node_utils::{config::load_config, crypto::get_rpo_random_coin}; use miden_objects::{ - accounts::{Account, AccountData, AccountStorageMode, AuthSecretKey}, + accounts::{Account, AccountData, AuthSecretKey}, assets::TokenSymbol, - crypto::{ - dsa::rpo_falcon512::SecretKey, - rand::RpoRandomCoin, - utils::{hex_to_bytes, Serializable}, - }, - Digest, Felt, ONE, + crypto::{dsa::rpo_falcon512::SecretKey, utils::Serializable}, + Felt, ONE, }; +use rand::Rng; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use tracing::info; mod inputs; @@ -80,13 +78,9 @@ pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: &bool) })?; info!("Genesis input file: {} has successfully been loaded.", inputs_path.display()); + let accounts_path = parent_path.join(DEFAULT_ACCOUNTS_DIR); let accounts = - create_accounts(&genesis_input.accounts.unwrap_or_default(), parent_path, force)?; - info!( - "Accounts have successfully been created at: {}/{}", - parent_path.display(), - DEFAULT_ACCOUNTS_DIR - ); + create_accounts(&genesis_input.accounts.unwrap_or_default(), &accounts_path, force)?; let genesis_state = GenesisState::new(accounts, genesis_input.version, genesis_input.timestamp); fs::write(output_path, genesis_state.to_bytes()).unwrap_or_else(|_| { @@ -102,13 +96,10 @@ pub fn make_genesis(inputs_path: &PathBuf, output_path: &PathBuf, force: &bool) /// This function also writes the account data files into the default accounts directory. fn create_accounts( accounts: &[AccountInput], - parent_path: &Path, + accounts_path: impl AsRef, force: &bool, ) -> Result> { - let mut accounts_path = PathBuf::from(&parent_path); - accounts_path.push(DEFAULT_ACCOUNTS_DIR); - - if accounts_path.try_exists()? { + if accounts_path.as_ref().try_exists()? { if !force { bail!( "Failed to create accounts directory because it already exists. \ @@ -121,21 +112,19 @@ fn create_accounts( fs::create_dir_all(&accounts_path).context("Failed to create accounts directory")?; let mut final_accounts = Vec::new(); + let mut faucet_count = 0; + let mut rng = ChaCha20Rng::from_seed(rand::random()); for account in accounts { // build offchain account data from account inputs - let mut account_data = match account { + let (mut account_data, name) = match account { AccountInput::BasicFungibleFaucet(inputs) => { info!("Creating fungible faucet account..."); - let init_seed = hex_to_bytes(&inputs.init_seed)?; - - let (auth_scheme, auth_secret_key) = - parse_auth_inputs(inputs.auth_scheme, &inputs.auth_seed)?; - - let storage_mode: AccountStorageMode = inputs.storage_mode.as_str().try_into()?; + let (auth_scheme, auth_secret_key) = gen_auth_keys(inputs.auth_scheme, &mut rng)?; + let storage_mode = inputs.storage_mode.as_str().try_into()?; let (account, account_seed) = create_basic_fungible_faucet( - init_seed, + rng.gen(), TokenSymbol::try_from(inputs.token_symbol.as_str())?, inputs.decimals, Felt::try_from(inputs.max_supply) @@ -144,23 +133,28 @@ fn create_accounts( auth_scheme, )?; - AccountData::new(account, Some(account_seed), auth_secret_key) + let name = format!( + "faucet{}", + (faucet_count > 0).then(|| faucet_count.to_string()).unwrap_or_default() + ); + faucet_count += 1; + + (AccountData::new(account, Some(account_seed), auth_secret_key), name) }, }; // write account data to file - let path = format!("{}/account{}.mac", accounts_path.display(), final_accounts.len()); - let path = Path::new(&path); + let path = accounts_path.as_ref().join(format!("{name}.mac")); - if let Ok(path_exists) = path.try_exists() { - if path_exists && !force { - bail!("Failed to generate account file {} because it already exists. Use the --force flag to overwrite.", path.display()); - } + if !force && matches!(path.try_exists(), Ok(true)) { + bail!("Failed to generate account file {} because it already exists. Use the --force flag to overwrite.", path.display()); } account_data.account.set_nonce(ONE)?; - account_data.write(path)?; + account_data.write(&path)?; + + info!("Account \"{name}\" has successfully been saved to: {}", path.display()); final_accounts.push(account_data.account); } @@ -168,21 +162,18 @@ fn create_accounts( Ok(final_accounts) } -fn parse_auth_inputs( +fn gen_auth_keys( auth_scheme_input: AuthSchemeInput, - auth_seed: &str, + rng: &mut ChaCha20Rng, ) -> Result<(AuthScheme, AuthSecretKey)> { match auth_scheme_input { AuthSchemeInput::RpoFalcon512 => { - let auth_seed: [u8; 32] = hex_to_bytes(auth_seed)?; - let rng_seed = Digest::try_from(&auth_seed)?.into(); - let mut rng = RpoRandomCoin::new(rng_seed); - let secret = SecretKey::with_rng(&mut rng); + let secret = SecretKey::with_rng(&mut get_rpo_random_coin(rng)); - let auth_scheme = AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }; - let auth_secret_key = AuthSecretKey::RpoFalcon512(secret); - - Ok((auth_scheme, auth_secret_key)) + Ok(( + AuthScheme::RpoFalcon512 { pub_key: secret.public_key() }, + AuthSecretKey::RpoFalcon512(secret), + )) }, } } @@ -215,9 +206,7 @@ mod tests { [[accounts]] type = "BasicFungibleFaucet" - init_seed = "0xc123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" - auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" token_symbol = "POL" decimals = 12 max_supply = 1000000 @@ -230,7 +219,7 @@ mod tests { // run make_genesis to generate genesis.dat and accounts folder and files make_genesis(&genesis_inputs_file_path, &genesis_dat_file_path, &true).unwrap(); - let a0_file_path = PathBuf::from("accounts/account0.mac"); + let a0_file_path = PathBuf::from("accounts/faucet.mac"); // assert that the genesis.dat and account files exist assert!(genesis_dat_file_path.exists()); diff --git a/bin/node/src/main.rs b/bin/node/src/main.rs index 1ce93c60b..1839d7484 100644 --- a/bin/node/src/main.rs +++ b/bin/node/src/main.rs @@ -127,11 +127,8 @@ async fn main() -> anyhow::Result<()> { let current_dir = std::env::current_dir() .map_err(|err| anyhow!("failed to open current directory: {err}"))?; - let mut config = current_dir.clone(); - let mut genesis = current_dir.clone(); - - config.push(config_path); - genesis.push(genesis_path); + let config = current_dir.join(config_path); + let genesis = current_dir.join(genesis_path); init_config_files(config, genesis) }, diff --git a/config/genesis.toml b/config/genesis.toml index 6a77d9a77..8c74a4dd3 100644 --- a/config/genesis.toml +++ b/config/genesis.toml @@ -5,9 +5,7 @@ timestamp = 1672531200 [[accounts]] type = "BasicFungibleFaucet" storage_mode = "public" -init_seed = "0xc123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" -auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" token_symbol = "POL" decimals = 12 max_supply = 1000000 diff --git a/config/miden-faucet.toml b/config/miden-faucet.toml index a9fdc1428..8124e33db 100644 --- a/config/miden-faucet.toml +++ b/config/miden-faucet.toml @@ -1,9 +1,5 @@ endpoint = { host = "localhost", port = 8080 } node_url = "http://localhost:57291" timeout_ms = 10000 - -# Data used to construct the faucet account of the faucet asset_amount_options = [100, 500, 1000] -token_symbol = "POL" -decimals = 8 -max_supply = 1000000 +faucet_account_path = "accounts/faucet.mac" diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index e3b4494d5..75f19675b 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -20,6 +20,7 @@ anyhow = { version = "1.0" } figment = { version = "0.10", features = ["toml", "env"] } itertools = { version = "0.12" } miden-objects = { workspace = true } +rand = { workspace = true } serde = { version = "1.0", features = ["derive"] } thiserror = { workspace = true } tonic = { workspace = true } diff --git a/crates/utils/src/crypto.rs b/crates/utils/src/crypto.rs new file mode 100644 index 000000000..f8a48aef2 --- /dev/null +++ b/crates/utils/src/crypto.rs @@ -0,0 +1,13 @@ +use miden_objects::{ + crypto::{hash::rpo::RpoDigest, rand::RpoRandomCoin}, + Felt, +}; +use rand::{Rng, RngCore}; + +/// Creates a new RPO Random Coin with random seed +pub fn get_rpo_random_coin(rng: &mut T) -> RpoRandomCoin { + let auth_seed: [u64; 4] = rng.gen(); + let rng_seed = RpoDigest::from(auth_seed.map(Felt::new)); + + RpoRandomCoin::new(rng_seed.into()) +} diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index b098bf2d8..275ee7e35 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -1,4 +1,5 @@ pub mod config; +pub mod crypto; pub mod errors; pub mod formatting; pub mod logging; From 49846e3ea60bf56222057883618d1cb6b0dabb77 Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Sat, 2 Nov 2024 10:30:23 -0700 Subject: [PATCH 9/9] chore: address comments --- CHANGELOG.md | 8 ++++---- Cargo.lock | 51 +++++++++++++++++++++++++++------------------------ Makefile | 2 +- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed2ecf837..7257a5da3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,21 +2,21 @@ ## v0.6.0 (TBD) -- Added `AccountCode` as part of `GetAccountProofs` endpoint response (#521). -- [BREAKING] Added `kernel_root` to block header's protobuf message definitions (#496). -- [BREAKING] Renamed `off-chain` and `on-chain` to `private` and `public` respectively for the account storage modes (#489). - Optimized state synchronizations by removing unnecessary fetching and parsing of note details (#462). - [BREAKING] Changed `GetAccountDetailsResponse` field to `details` (#481). - Improve `--version` by adding build metadata (#495). +- [BREAKING] Added `kernel_root` to block header's protobuf message definitions (#496). +- [BREAKING] Renamed `off-chain` and `on-chain` to `private` and `public` respectively for the account storage modes (#489). - [BREAKING] Introduced additional limits for note/account number (#503). - [BREAKING] Removed support for basic wallets in genesis creation (#510). - Added `GetAccountProofs` endpoint (#506). - Migrated faucet from actix-web to axum (#511). - Changed the `BlockWitness` to pass the inputs to the VM using only advice provider (#516). +- [BREAKING] Changed faucet storage type in the genesis to public. Using faucet from the genesis for faucet web app. Added support for faucet restarting without blockchain restarting (#517). - [BREAKING] Improved store API errors (return "not found" instead of "internal error" status if requested account(s) not found) (#518). +- Added `AccountCode` as part of `GetAccountProofs` endpoint response (#521). - [BREAKING] Migrated to v0.11 version of Miden VM (#528). - Reduce cloning in the store's `apply_block` (#532). -- [BREAKING] Changed faucet storage type in the genesis to public. Using faucet from the genesis for faucet web app. Added support for faucet restarting without blockchain restarting (#517). ## 0.5.1 (2024-09-12) diff --git a/Cargo.lock b/Cargo.lock index 7456d865a..4de7bc004 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -104,9 +104,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" [[package]] name = "arrayref" @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.31" +version = "1.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" dependencies = [ "jobserver", "libc", @@ -912,8 +912,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1284,9 +1286,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00419de735aac21d53b0de5ce2c03bd3627277cf471300f27ebc89f7d828047" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1402,7 +1404,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miden-air" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "miden-core", "miden-thiserror", @@ -1413,7 +1415,7 @@ dependencies = [ [[package]] name = "miden-assembly" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "aho-corasick", "lalrpop", @@ -1430,7 +1432,7 @@ dependencies = [ [[package]] name = "miden-core" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "lock_api", "loom", @@ -1506,7 +1508,7 @@ dependencies = [ [[package]] name = "miden-lib" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#f621c437bd5eb67d7b4a82d98a3eec8d238bb6cb" dependencies = [ "miden-assembly", "miden-objects", @@ -1703,8 +1705,9 @@ dependencies = [ [[package]] name = "miden-objects" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#f621c437bd5eb67d7b4a82d98a3eec8d238bb6cb" dependencies = [ + "getrandom", "miden-assembly", "miden-core", "miden-crypto", @@ -1717,7 +1720,7 @@ dependencies = [ [[package]] name = "miden-processor" version = "0.10.6" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "miden-air", "miden-core", @@ -1728,7 +1731,7 @@ dependencies = [ [[package]] name = "miden-prover" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "miden-air", "miden-processor", @@ -1743,7 +1746,7 @@ version = "0.6.0" [[package]] name = "miden-stdlib" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "miden-assembly", ] @@ -1771,7 +1774,7 @@ dependencies = [ [[package]] name = "miden-tx" version = "0.6.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#b624d0810b1b3813f106aa38b796b9d62a39265d" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#f621c437bd5eb67d7b4a82d98a3eec8d238bb6cb" dependencies = [ "async-trait", "miden-assembly", @@ -1790,7 +1793,7 @@ dependencies = [ [[package]] name = "miden-verifier" version = "0.10.5" -source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#9f9cc63b709d8b7c83841d8e421701dcd33792bb" +source = "git+https://github.com/0xPolygonMiden/miden-vm.git?branch=next#f1c0553859c42c56f28d1d6aaf66d3e2f9907bd1" dependencies = [ "miden-air", "miden-core", @@ -2804,9 +2807,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -2887,18 +2890,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" dependencies = [ "proc-macro2", "quote", diff --git a/Makefile b/Makefile index b10ad72a9..afa1a2da9 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ BUILD_PROTO=BUILD_PROTO=1 .PHONY: clippy clippy: ## Runs Clippy with configs - cargo clippy --locked --workspace --all-targets --all-features -- -D warnings --allow clippy::arc_with_non_send_sync + cargo clippy --locked --workspace --all-targets --all-features -- -D warnings .PHONY: fix