From 0b13efec2c508ba7fb692d6105bcb3c08b0149c6 Mon Sep 17 00:00:00 2001 From: igamigo Date: Wed, 16 Oct 2024 13:42:38 -0300 Subject: [PATCH] feat: Add `RemoteTransactionProver` struct (#921) * feat: Add remote prover struct * Remove unused comment * Add no_std * CHANGELOG * Format * Change no_std attr * Change std/nostd addressing * Change features * Conditionally use transport based on target arch * Rename error --- CHANGELOG.md | 1 + Cargo.lock | 424 ++++++++++-------- Cargo.toml | 2 +- bin/tx-prover/Cargo.toml | 61 ++- bin/tx-prover/README.md | 11 +- bin/tx-prover/build.rs | 73 ++- bin/tx-prover/src/{server => api}/mod.rs | 46 +- bin/tx-prover/src/generated/mod.rs | 29 ++ bin/tx-prover/src/generated/nostd/api.rs | 114 +++++ bin/tx-prover/src/generated/nostd/mod.rs | 2 + .../generated => generated/std}/api.rs | 82 ++-- bin/tx-prover/src/generated/std/mod.rs | 2 + bin/tx-prover/src/lib.rs | 24 + bin/tx-prover/src/main.rs | 21 +- bin/tx-prover/src/prover.rs | 78 ++++ bin/tx-prover/src/server/generated/mod.rs | 1 - miden-tx/src/errors/mod.rs | 10 +- miden-tx/src/prover/mod.rs | 2 +- 18 files changed, 657 insertions(+), 326 deletions(-) rename bin/tx-prover/src/{server => api}/mod.rs (58%) create mode 100644 bin/tx-prover/src/generated/mod.rs create mode 100644 bin/tx-prover/src/generated/nostd/api.rs create mode 100644 bin/tx-prover/src/generated/nostd/mod.rs rename bin/tx-prover/src/{server/generated => generated/std}/api.rs (85%) create mode 100644 bin/tx-prover/src/generated/std/mod.rs create mode 100644 bin/tx-prover/src/lib.rs create mode 100644 bin/tx-prover/src/prover.rs delete mode 100644 bin/tx-prover/src/server/generated/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c59c4869e..593e4992a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 0.6.0 (TBD) +- Added `RemoteTransactionProver` struct to `miden-tx-prover` (#921). - [BREAKING] Changed `TransactionProver` trait to be `maybe_async_trait` based on the `async` feature (#913). - [BREAKING] Changed `TransactionExecutor` and `TransactionHost` to use trait objects (#897). - Implemented kernel procedure to set transaction expiration block delta (#897). diff --git a/Cargo.lock b/Cargo.lock index 52c2de050..f153176a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,38 +99,16 @@ dependencies = [ ] [[package]] -name = "autocfg" -version = "1.4.0" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "axum" -version = "0.6.20" +name = "autocfg" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower 0.4.13", - "tower-layer", - "tower-service", -] +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" @@ -139,13 +117,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", - "axum-core 0.4.5", + "axum-core", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "itoa", "matchit", @@ -166,23 +144,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.5" @@ -192,8 +153,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -230,9 +191,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "beef" @@ -255,12 +216,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -289,6 +244,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -309,9 +270,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -353,18 +314,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstyle", "clap_lex", @@ -686,8 +647,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -704,16 +667,16 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.26" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 0.2.12", + "http", "indexmap 2.6.0", "slab", "tokio", @@ -761,17 +724,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[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" @@ -783,17 +735,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -801,7 +742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -812,17 +753,11 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" - [[package]] name = "httparse" version = "1.9.5" @@ -837,57 +772,36 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.30" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "smallvec", "tokio", + "want", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.30", + "hyper", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -897,13 +811,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", + "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http", + "http-body", + "hyper", "pin-project-lite", + "socket2", "tokio", "tower-service", + "tracing", ] [[package]] @@ -969,9 +886,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -991,6 +908,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "keccak" version = "0.1.5" @@ -1051,7 +977,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", ] @@ -1383,10 +1309,11 @@ dependencies = [ name = "miden-tx-prover" version = "0.6.0" dependencies = [ - "axum 0.7.7", + "async-trait", + "axum", + "getrandom", "miden-lib", "miden-objects", - "miden-prover", "miden-tx", "miette", "prost", @@ -1397,8 +1324,10 @@ dependencies = [ "tonic", "tonic-build", "tonic-web", + "tonic-web-wasm-client", "tracing", "tracing-subscriber", + "winter-maybe-async 0.10.1", ] [[package]] @@ -1727,18 +1656,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", "prost-derive", @@ -1746,13 +1675,13 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -1767,12 +1696,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn", @@ -1780,9 +1709,9 @@ dependencies = [ [[package]] name = "prost-reflect" -version = "0.13.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5eec97d5d34bdd17ad2db2219aabf46b054c6c41bd5529767c9ce55be5898f" +checksum = "4b7535b02f0e5efe3e1dbfcb428be152226ed0c66cad9541f2274c8ba8d4cd40" dependencies = [ "logos", "miette", @@ -1793,18 +1722,18 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ "prost", ] [[package]] name = "protox" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac532509cee918d40f38c3e12f8ef9230f215f017d54de7dd975015538a42ce7" +checksum = "873f359bdecdfe6e353752f97cb9ee69368df55b16363ed2216da85e03232a58" dependencies = [ "bytes", "miette", @@ -1817,9 +1746,9 @@ dependencies = [ [[package]] name = "protox-parse" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6c33f43516fe397e2f930779d720ca12cd057f7da4cd6326a0ef78d69dee96" +checksum = "a3a462d115462c080ae000c29a47f0b3985737e5d3a995fcdbcaa5c782068dde" dependencies = [ "logos", "miette", @@ -1892,7 +1821,7 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -2016,7 +1945,7 @@ version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2025,9 +1954,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 = "ryu" @@ -2405,16 +2334,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.4.0" @@ -2486,23 +2405,26 @@ dependencies = [ [[package]] name = "tonic" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.6.20", + "axum", "base64", "bytes", "h2", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", "prost", + "socket2", "tokio", "tokio-stream", "tower 0.4.13", @@ -2513,28 +2435,29 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", "syn", ] [[package]] name = "tonic-web" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc3b0e1cedbf19fdfb78ef3d672cb9928e0a91a9cb4629cc0c916e8cff8aaaa1" +checksum = "5299dd20801ad736dccb4a5ea0da7376e59cd98f213bf1c3d478cf53f4834b58" dependencies = [ "base64", "bytes", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", + "http", + "http-body", + "http-body-util", "pin-project", "tokio-stream", "tonic", @@ -2544,6 +2467,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic-web-wasm-client" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5ca6e7bdd0042c440d36b6df97c1436f1d45871ce18298091f114004b1beb4" +dependencies = [ + "base64", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "tower" version = "0.4.13" @@ -2582,17 +2530,15 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.6.0", + "bitflags", "bytes", - "futures-core", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "http-range-header", + "http", + "http-body", + "http-body-util", "pin-project-lite", "tower-layer", "tower-service", @@ -2693,9 +2639,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207aa50d36c4be8d8c6ea829478be44a372c6a77669937bb39c698e52f1491e8" +checksum = "8923cde76a6329058a86f04d033f0945a2c6df8b94093512e4ab188b3e3a8950" dependencies = [ "dissimilar", "glob", @@ -2799,6 +2745,96 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "wasm-streams" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 339215a60..2e6908be9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ miden-lib = { path = "miden-lib", version = "0.6", default-features = false } miden-objects = { path = "objects", version = "0.6", default-features = false } miden-prover = { version = "0.10", default-features = false } miden-stdlib = { version = "0.10", default-features = false } -miden-tx = { path = "miden-tx", version = "0.6" } +miden-tx = { path = "miden-tx", version = "0.6", default-features = false } miden-verifier = { version = "0.10", default-features = false } rand = { version = "0.8", default-features = false } vm-core = { package = "miden-core", version = "0.10", default-features = false } diff --git a/bin/tx-prover/Cargo.toml b/bin/tx-prover/Cargo.toml index dc8f5dcc7..499a27b88 100644 --- a/bin/tx-prover/Cargo.toml +++ b/bin/tx-prover/Cargo.toml @@ -11,30 +11,49 @@ repository.workspace = true rust-version.workspace = true edition.workspace = true +[[bin]] +name = "prover-service" +path = "src/main.rs" +required-features = ["std"] + +[lib] +crate-type = ["lib"] + [features] -testing = ["miden-objects/testing", "miden-lib/testing", "miden-tx/testing"] +async = ["miden-tx/async"] +default = ["std"] +std = ["miden-objects/std", "miden-tx/std", "dep:tokio", "dep:tonic-web", "dep:tokio-stream", "dep:axum", "dep:tracing", "dep:tracing-subscriber", "tonic/transport"] + +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +tonic-web-wasm-client = { version = "0.6", default-features = false } +tonic = { version = "0.12", default-features = false, features = ["prost", "codegen"] } +getrandom = { version = "0.2", features = ["js"], optional = true } + +[target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies] +tonic = { version = "0.12", default-features = false, features = ["prost", "codegen", "transport"] } [dependencies] -axum = "0.7" -miden-lib = { workspace = true } -miden-objects = { workspace = true } -miden-prover = { workspace = true } -miden-tx = { workspace = true } -prost = "0.12" -tokio = { version = "1.38", features = ["full"] } -tokio-stream = { version = "0.1", features = [ "net" ]} -tonic = "0.11" -tonic-web = { version = "0.11" } -tracing = { version = "0.1" } -tracing-subscriber = { version = "0.3", features = ["fmt", "json", "env-filter"] } +async-trait = "0.1" +axum = {version = "0.7", optional = true } +miden-lib = { workspace = true, default-features = false } +miden-objects = { workspace = true, default-features = false } +miden-tx = { workspace = true, default-features = false } +prost = { version = "0.13", default-features = false, features = ["derive"] } +tokio = { version = "1.38", optional = true, features = ["full"] } +tokio-stream = { version = "0.1", optional = true, features = [ "net" ]} +tonic-web = { version = "0.12", optional = true } +tracing = { version = "0.1", optional = true } +tracing-subscriber = { version = "0.3", features = ["fmt", "json", "env-filter"], optional = true } +winter-maybe-async = { version = "0.10" } + +[dev-dependencies] +miden-lib = { workspace = true , default-features = false, features = ["testing"]} +miden-objects = { workspace = true, default-features = false, features = ["testing"] } +miden-tx = { workspace = true, default-features = false, features = ["testing"] } [build-dependencies] miette = { version = "7.2", features = ["fancy"] } -prost = { version = "0.12" } -prost-build = { version = "0.12" } -protox = { version = "0.6" } -tonic-build = { version = "0.11" } - -[dev-dependencies] -tokio = { version = "1.38", features = ["full"] } -tonic = "0.11" +prost = { version = "0.13", default-features = false, features = ["derive"] } +prost-build = { version = "0.13" } +protox = { version = "0.7" } +tonic-build = { version = "0.12" } diff --git a/bin/tx-prover/README.md b/bin/tx-prover/README.md index 135aba96d..2f46db59a 100644 --- a/bin/tx-prover/README.md +++ b/bin/tx-prover/README.md @@ -29,7 +29,7 @@ cargo install --locked --git https://github.com/0xPolygonMiden/miden-base miden- cargo install --locked --git https://github.com/0xPolygonMiden/miden-base miden-tx-prover --rev ``` -If you want to build the prover from a local version, you can run: +If you want to build the prover from a local version, from the root of the workspace you can run: ```bash make install-prover @@ -52,3 +52,12 @@ PROVER_SERVICE_HOST= PROVER_SERVICE_PORT= RUST_LOG= ``` + +### Using RemoteTransactionProver +To use the `RemoteTransactionProver` struct, enable `async`. Additionally, when compiling for `wasm32-unknown-unknown`, disable default features. + +``` +[dependencies] +miden-tx-prover = { version = "0.6", features = ["async"], default-features = false } # Uses tonic-web-wasm-client transport +miden-tx-prover = { version = "0.6", features = ["async"] } # Uses tonic's Channel transport +``` diff --git a/bin/tx-prover/build.rs b/bin/tx-prover/build.rs index 09a9e5fec..994557dc9 100644 --- a/bin/tx-prover/build.rs +++ b/bin/tx-prover/build.rs @@ -1,4 +1,8 @@ -use std::{env, fs, path::PathBuf}; +use std::{ + env, fs, + io::Write, + path::{Path, PathBuf}, +}; use miette::IntoDiagnostic; use protox::prost::Message; @@ -9,38 +13,63 @@ fn main() -> miette::Result<()> { Ok(()) } - fn compile_tonic_server_proto() -> miette::Result<()> { - let crate_root: PathBuf = - env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should be set").into(); - let dst_dir = crate_root.join("src").join("server").join("generated"); - - // Remove api.rs file if exists. - let _ = fs::remove_file(dst_dir.join("api.rs")).into_diagnostic(); + let crate_root = + PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should be set")); + let dst_dir = crate_root.join("src").join("generated"); + let proto_dir = crate_root.join("proto"); - // Compute the directory of the `proto` definitions - let proto_dir: PathBuf = crate_root.join("proto"); + // Remove `api.rs` if it exists. + fs::remove_file(dst_dir.join("api.rs")).into_diagnostic().ok(); - // Compute the compiler's target file path. - let out = env::var("OUT_DIR").into_diagnostic()?; - let file_descriptor_path = PathBuf::from(out).join("file_descriptor_set.bin"); + let out_dir = env::var("OUT_DIR").into_diagnostic()?; + let file_descriptor_path = PathBuf::from(out_dir).join("file_descriptor_set.bin"); - // Compile the proto file for all servers APIs let protos = &[proto_dir.join("api.proto")]; - let includes = &[proto_dir]; + let file_descriptors = protox::compile(protos, includes)?; fs::write(&file_descriptor_path, file_descriptors.encode_to_vec()).into_diagnostic()?; - let prost_config = prost_build::Config::new(); + // Codegen for wasm transport and std transport + let nostd_path = dst_dir.join("nostd"); + let std_path = dst_dir.join("std"); + build_tonic_server(&file_descriptor_path, &std_path, protos, includes, false)?; + build_tonic_server(&file_descriptor_path, &nostd_path, protos, includes, true)?; - // Generate the stub of the user facing server from its proto file - tonic_build::configure() - .file_descriptor_set_path(&file_descriptor_path) - .skip_protoc_run() - .out_dir(&dst_dir) - .compile_with_config(prost_config, protos, includes) + // Replace `std` references with `core` and `alloc` in `api.rs`. + // (Only for nostd version) + let nostd_file_path = nostd_path.join("api.rs"); + let file_content = fs::read_to_string(&nostd_file_path).into_diagnostic()?; + let updated_content = file_content + .replace("std::result", "core::result") + .replace("std::marker", "core::marker") + .replace("format!", "alloc::format!"); + + let mut file = fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(&nostd_file_path) .into_diagnostic()?; + file.write_all(updated_content.as_bytes()).into_diagnostic()?; + Ok(()) } + +fn build_tonic_server( + file_descriptor_path: &Path, + out_dir: &Path, + protos: &[PathBuf], + includes: &[PathBuf], + for_no_std: bool, +) -> miette::Result<()> { + tonic_build::configure() + .file_descriptor_set_path(file_descriptor_path) + .skip_protoc_run() + .out_dir(out_dir) + .build_server(!for_no_std) + .build_transport(!for_no_std) + .compile_protos_with_config(prost_build::Config::new(), protos, includes) + .into_diagnostic() +} diff --git a/bin/tx-prover/src/server/mod.rs b/bin/tx-prover/src/api/mod.rs similarity index 58% rename from bin/tx-prover/src/server/mod.rs rename to bin/tx-prover/src/api/mod.rs index 370634dc2..2572846a3 100644 --- a/bin/tx-prover/src/server/mod.rs +++ b/bin/tx-prover/src/api/mod.rs @@ -1,6 +1,4 @@ -use generated::api::{api_server, ProveTransactionRequest, ProveTransactionResponse}; -use miden_objects::transaction::{ProvenTransaction, TransactionWitness}; -use miden_prover::DeserializationError; +use miden_objects::transaction::TransactionWitness; use miden_tx::{ utils::{Deserializable, Serializable}, LocalTransactionProver, TransactionProver, @@ -9,33 +7,32 @@ use tokio::{net::TcpListener, sync::Mutex}; use tonic::{Request, Response, Status}; use tracing::info; -#[rustfmt::skip] -pub mod generated; +use crate::{ApiServer, ProveTransactionRequest, ProveTransactionResponse, ProverApi}; -pub struct Rpc { - pub api_service: api_server::ApiServer, +pub struct RpcListener { + pub api_service: ApiServer, pub listener: TcpListener, } -impl Rpc { +impl RpcListener { pub fn new(listener: TcpListener) -> Self { - let api_service = api_server::ApiServer::new(RpcApi::default()); + let api_service = ApiServer::new(ProverRpcApi::default()); Self { listener, api_service } } } #[derive(Default)] -pub struct RpcApi { - prover: Mutex, +pub struct ProverRpcApi { + local_prover: Mutex, } // We need to implement Send and Sync for the generated code to be able to use the prover in the // shared context. -unsafe impl Send for RpcApi {} -unsafe impl Sync for RpcApi {} +unsafe impl Send for ProverRpcApi {} +unsafe impl Sync for ProverRpcApi {} -#[tonic::async_trait] -impl api_server::Api for RpcApi { +#[async_trait::async_trait] +impl ProverApi for ProverRpcApi { async fn prove_transaction( &self, request: Request, @@ -44,7 +41,7 @@ impl api_server::Api for RpcApi { // Try to acquire a permit without waiting let prover = self - .prover + .local_prover .try_lock() .map_err(|_| Status::resource_exhausted("Server is busy handling another request"))?; @@ -58,23 +55,6 @@ impl api_server::Api for RpcApi { } } -// CONVERSIONS -// ================================================================================================ - -impl From for ProveTransactionResponse { - fn from(value: ProvenTransaction) -> Self { - ProveTransactionResponse { proven_transaction: value.to_bytes() } - } -} - -impl TryFrom for ProvenTransaction { - type Error = DeserializationError; - - fn try_from(response: ProveTransactionResponse) -> Result { - ProvenTransaction::read_from_bytes(&response.proven_transaction) - } -} - // UTILITIES // ================================================================================================ diff --git a/bin/tx-prover/src/generated/mod.rs b/bin/tx-prover/src/generated/mod.rs new file mode 100644 index 000000000..644ab21cf --- /dev/null +++ b/bin/tx-prover/src/generated/mod.rs @@ -0,0 +1,29 @@ +use miden_objects::transaction::ProvenTransaction; +use miden_tx::utils::{Deserializable, DeserializationError, Serializable}; + +#[cfg(feature = "std")] +mod std; +#[cfg(feature = "std")] +pub use std::api::*; + +#[cfg(target_arch = "wasm32")] +mod nostd; +#[cfg(target_arch = "wasm32")] +pub use nostd::api::*; + +// CONVERSIONS +// ================================================================================================ + +impl From for ProveTransactionResponse { + fn from(value: ProvenTransaction) -> Self { + ProveTransactionResponse { proven_transaction: value.to_bytes() } + } +} + +impl TryFrom for ProvenTransaction { + type Error = DeserializationError; + + fn try_from(response: ProveTransactionResponse) -> Result { + ProvenTransaction::read_from_bytes(&response.proven_transaction) + } +} diff --git a/bin/tx-prover/src/generated/nostd/api.rs b/bin/tx-prover/src/generated/nostd/api.rs new file mode 100644 index 000000000..8c84619ac --- /dev/null +++ b/bin/tx-prover/src/generated/nostd/api.rs @@ -0,0 +1,114 @@ +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProveTransactionRequest { + #[prost(bytes = "vec", tag = "1")] + pub transaction_witness: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProveTransactionResponse { + #[prost(bytes = "vec", tag = "1")] + pub proven_transaction: ::prost::alloc::vec::Vec, +} +/// Generated client implementations. +pub mod api_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ApiClient { + inner: tonic::client::Grpc, + } + impl ApiClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + core::marker::Send + 'static, + ::Error: Into + core::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ApiClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + core::marker::Send + core::marker::Sync, + { + ApiClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn prove_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> core::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + alloc::format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static("/api.Api/ProveTransaction"); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new("api.Api", "ProveTransaction")); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/bin/tx-prover/src/generated/nostd/mod.rs b/bin/tx-prover/src/generated/nostd/mod.rs new file mode 100644 index 000000000..1b28e9b38 --- /dev/null +++ b/bin/tx-prover/src/generated/nostd/mod.rs @@ -0,0 +1,2 @@ +#[rustfmt::skip] +pub mod api; diff --git a/bin/tx-prover/src/server/generated/api.rs b/bin/tx-prover/src/generated/std/api.rs similarity index 85% rename from bin/tx-prover/src/server/generated/api.rs rename to bin/tx-prover/src/generated/std/api.rs index 082a941d1..fa143409e 100644 --- a/bin/tx-prover/src/server/generated/api.rs +++ b/bin/tx-prover/src/generated/std/api.rs @@ -1,11 +1,9 @@ // This file is @generated by prost-build. -#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProveTransactionRequest { #[prost(bytes = "vec", tag = "1")] pub transaction_witness: ::prost::alloc::vec::Vec, } -#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProveTransactionResponse { #[prost(bytes = "vec", tag = "1")] @@ -13,7 +11,13 @@ pub struct ProveTransactionResponse { } /// Generated client implementations. pub mod api_client { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] use tonic::codegen::*; use tonic::codegen::http::Uri; #[derive(Debug, Clone)] @@ -35,8 +39,8 @@ pub mod api_client { where T: tonic::client::GrpcService, T::Error: Into, - T::ResponseBody: Body + Send + 'static, - ::Error: Into + Send, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); @@ -61,7 +65,7 @@ pub mod api_client { >, , - >>::Error: Into + Send + Sync, + >>::Error: Into + std::marker::Send + std::marker::Sync, { ApiClient::new(InterceptedService::new(inner, interceptor)) } @@ -107,8 +111,7 @@ pub mod api_client { .ready() .await .map_err(|e| { - tonic::Status::new( - tonic::Code::Unknown, + tonic::Status::unknown( format!("Service was not ready: {}", e.into()), ) })?; @@ -122,11 +125,17 @@ pub mod api_client { } /// Generated server implementations. pub mod api_server { - #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with ApiServer. #[async_trait] - pub trait Api: Send + Sync + 'static { + pub trait Api: std::marker::Send + std::marker::Sync + 'static { async fn prove_transaction( &self, request: tonic::Request, @@ -136,20 +145,18 @@ pub mod api_server { >; } #[derive(Debug)] - pub struct ApiServer { - inner: _Inner, + pub struct ApiServer { + inner: Arc, accept_compression_encodings: EnabledCompressionEncodings, send_compression_encodings: EnabledCompressionEncodings, max_decoding_message_size: Option, max_encoding_message_size: Option, } - struct _Inner(Arc); - impl ApiServer { + impl ApiServer { pub fn new(inner: T) -> Self { Self::from_arc(Arc::new(inner)) } pub fn from_arc(inner: Arc) -> Self { - let inner = _Inner(inner); Self { inner, accept_compression_encodings: Default::default(), @@ -199,8 +206,8 @@ pub mod api_server { impl tonic::codegen::Service> for ApiServer where T: Api, - B: Body + Send + 'static, - B::Error: Into + Send + 'static, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, { type Response = http::Response; type Error = std::convert::Infallible; @@ -212,7 +219,6 @@ pub mod api_server { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { - let inner = self.inner.clone(); match req.uri().path() { "/api.Api/ProveTransaction" => { #[allow(non_camel_case_types)] @@ -243,7 +249,6 @@ pub mod api_server { let max_encoding_message_size = self.max_encoding_message_size; let inner = self.inner.clone(); let fut = async move { - let inner = inner.0; let method = ProveTransactionSvc(inner); let codec = tonic::codec::ProstCodec::default(); let mut grpc = tonic::server::Grpc::new(codec) @@ -262,20 +267,25 @@ pub mod api_server { } _ => { Box::pin(async move { - Ok( - http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap(), - ) + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) }) } } } } - impl Clone for ApiServer { + impl Clone for ApiServer { fn clone(&self) -> Self { let inner = self.inner.clone(); Self { @@ -287,17 +297,9 @@ pub mod api_server { } } } - impl Clone for _Inner { - fn clone(&self) -> Self { - Self(Arc::clone(&self.0)) - } - } - impl std::fmt::Debug for _Inner { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) - } - } - impl tonic::server::NamedService for ApiServer { - const NAME: &'static str = "api.Api"; + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "api.Api"; + impl tonic::server::NamedService for ApiServer { + const NAME: &'static str = SERVICE_NAME; } } diff --git a/bin/tx-prover/src/generated/std/mod.rs b/bin/tx-prover/src/generated/std/mod.rs new file mode 100644 index 000000000..1b28e9b38 --- /dev/null +++ b/bin/tx-prover/src/generated/std/mod.rs @@ -0,0 +1,2 @@ +#[rustfmt::skip] +pub mod api; diff --git a/bin/tx-prover/src/lib.rs b/bin/tx-prover/src/lib.rs new file mode 100644 index 000000000..a3c7e6e29 --- /dev/null +++ b/bin/tx-prover/src/lib.rs @@ -0,0 +1,24 @@ +extern crate alloc; +use alloc::string::String; + +pub(crate) mod generated; + +#[cfg(feature = "async")] +mod prover; +#[cfg(feature = "async")] +pub use prover::RemoteTransactionProver; + +/// Contains the protobuf definitions +pub const PROTO_MESSAGES: &str = include_str!("../proto/api.proto"); + +/// ERRORS +/// =============================================================================================== + +#[derive(Debug)] +pub enum RemoteTransactionProverError { + /// Indicates that the provided gRPC server endpoint is invalid. + InvalidEndpoint(String), + + /// Indicates that the connection to the server failed. + ConnectionFailed(String), +} diff --git a/bin/tx-prover/src/main.rs b/bin/tx-prover/src/main.rs index d1f855ef6..79e857e2f 100644 --- a/bin/tx-prover/src/main.rs +++ b/bin/tx-prover/src/main.rs @@ -1,11 +1,16 @@ use std::env; -use server::Rpc; +use api::RpcListener; use tokio::net::TcpListener; use tokio_stream::wrappers::TcpListenerStream; use tracing::info; +mod api; -pub mod server; +mod generated; +pub use generated::{ + api_server::{Api as ProverApi, ApiServer}, + ProveTransactionRequest, ProveTransactionResponse, +}; #[tokio::main] async fn main() -> Result<(), Box> { @@ -16,7 +21,7 @@ async fn main() -> Result<(), Box> { let port = env::var("PROVER_SERVICE_PORT").unwrap_or_else(|_| "50051".to_string()); let addr = format!("{}:{}", host, port); - let rpc = Rpc::new(TcpListener::bind(addr).await?); + let rpc = RpcListener::new(TcpListener::bind(addr).await?); info!("Server listening on {}", rpc.listener.local_addr()?); @@ -49,20 +54,18 @@ mod test { testing::mock_chain::{Auth, MockChain}, utils::Serializable, }; - use server::{ - generated::api::{api_client::ApiClient, api_server::ApiServer, ProveTransactionRequest}, - RpcApi, - }; use tokio::net::TcpListener; use tonic::Request; - use super::*; + use crate::{ + api::ProverRpcApi, generated::api_client::ApiClient, ApiServer, ProveTransactionRequest, + }; #[tokio::test(flavor = "multi_thread", worker_threads = 3)] async fn test_prove_transaction() { // Start the server in the background let listener = TcpListener::bind("127.0.0.1:50052").await.unwrap(); - let api_service = ApiServer::new(RpcApi::default()); + let api_service = ApiServer::new(ProverRpcApi::default()); // Spawn the server as a background task tokio::spawn(async move { diff --git a/bin/tx-prover/src/prover.rs b/bin/tx-prover/src/prover.rs new file mode 100644 index 000000000..76c742318 --- /dev/null +++ b/bin/tx-prover/src/prover.rs @@ -0,0 +1,78 @@ +use alloc::{boxed::Box, string::ToString}; +use core::cell::RefCell; + +use miden_objects::transaction::{ProvenTransaction, TransactionWitness}; +use miden_tx::{TransactionProver, TransactionProverError}; + +use crate::{generated::api_client::ApiClient, RemoteTransactionProverError}; + +// REMOTE TRANSACTION PROVER +// ================================================================================================ + +/// A [RemoteTransactionProver] is a transaction prover that sends witness data to a remote +/// gRPC server and receives a proven transaction. +#[derive(Clone)] +pub struct RemoteTransactionProver { + #[cfg(target_arch = "wasm32")] + client: RefCell>, + + #[cfg(not(target_arch = "wasm32"))] + client: RefCell>, +} + +impl RemoteTransactionProver { + /// Creates a new [RemoteTransactionProver] with the specified gRPC server endpoint. + /// This instantiates a tonic client that attempts connecting with the server. + /// + /// When compiled for the `wasm32-unknown-unknown` target, it uses the `tonic_web_wasm_client` + /// transport. Otherwise, it uses the built-in `tonic::transport` for native platforms. + /// + /// # Errors + /// + /// This function will return an error if the endpoint is invalid or if the gRPC + /// connection to the server cannot be established. + pub async fn new(endpoint: &str) -> Result { + #[cfg(target_arch = "wasm32")] + let client = { + let web_client = tonic_web_wasm_client::Client::new(endpoint.to_string()); + ApiClient::new(web_client) + }; + + #[cfg(not(target_arch = "wasm32"))] + let client = ApiClient::connect(endpoint.to_string()) + .await + .map_err(|_| RemoteTransactionProverError::ConnectionFailed(endpoint.to_string()))?; + + Ok(RemoteTransactionProver { client: RefCell::new(client) }) + } +} + +#[async_trait::async_trait(?Send)] +impl TransactionProver for RemoteTransactionProver { + async fn prove( + &self, + tx_witness: TransactionWitness, + ) -> Result { + use miden_objects::utils::Serializable; + let mut client = self.client.borrow_mut(); + + let request = tonic::Request::new(crate::generated::ProveTransactionRequest { + transaction_witness: tx_witness.to_bytes(), + }); + + let response = client + .prove_transaction(request) + .await + .map_err(|err| TransactionProverError::InternalError(err.to_string()))?; + + // Deserialize the response bytes back into a ProvenTransaction. + let proven_transaction = + ProvenTransaction::try_from(response.into_inner()).map_err(|_| { + TransactionProverError::InternalError( + "Error deserializing received response".to_string(), + ) + })?; + + Ok(proven_transaction) + } +} diff --git a/bin/tx-prover/src/server/generated/mod.rs b/bin/tx-prover/src/server/generated/mod.rs deleted file mode 100644 index e5fdf85ee..000000000 --- a/bin/tx-prover/src/server/generated/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod api; diff --git a/miden-tx/src/errors/mod.rs b/miden-tx/src/errors/mod.rs index a86f6936a..9df361bd6 100644 --- a/miden-tx/src/errors/mod.rs +++ b/miden-tx/src/errors/mod.rs @@ -44,18 +44,19 @@ impl std::error::Error for TransactionExecutorError {} #[derive(Debug, Clone, PartialEq, Eq)] pub enum TransactionProverError { - ProveTransactionProgramFailed(ExecutionError), + InternalError(String), InvalidAccountDelta(AccountError), InvalidTransactionOutput(TransactionOutputError), ProvenTransactionError(ProvenTransactionError), + TransactionProgramExecutionFailed(ExecutionError), TransactionHostCreationFailed(TransactionHostError), } impl Display for TransactionProverError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - TransactionProverError::ProveTransactionProgramFailed(inner) => { - write!(f, "Proving transaction failed: {}", inner) + TransactionProverError::InternalError(inner) => { + write!(f, "Internal transaction prover error: {}", inner) }, TransactionProverError::InvalidAccountDelta(account_error) => { write!(f, "Applying account delta failed: {}", account_error) @@ -66,6 +67,9 @@ impl Display for TransactionProverError { TransactionProverError::ProvenTransactionError(inner) => { write!(f, "Building proven transaction error: {}", inner) }, + TransactionProverError::TransactionProgramExecutionFailed(inner) => { + write!(f, "Proving transaction failed: {}", inner) + }, TransactionProverError::TransactionHostCreationFailed(inner) => { write!(f, "Failed to create the transaction host: {}", inner) }, diff --git a/miden-tx/src/prover/mod.rs b/miden-tx/src/prover/mod.rs index 12085f5d5..dc7ba4b30 100644 --- a/miden-tx/src/prover/mod.rs +++ b/miden-tx/src/prover/mod.rs @@ -93,7 +93,7 @@ impl TransactionProver for LocalTransactionProver { .map_err(TransactionProverError::TransactionHostCreationFailed)?; let (stack_outputs, proof) = prove(&TransactionKernel::main(), stack_inputs, &mut host, self.proof_options.clone()) - .map_err(TransactionProverError::ProveTransactionProgramFailed)?; + .map_err(TransactionProverError::TransactionProgramExecutionFailed)?; // extract transaction outputs and process transaction data let (advice_provider, account_delta, output_notes, _signatures, _tx_progress) =