diff --git a/fhevm-engine/Cargo.lock b/fhevm-engine/Cargo.lock index d05e7e2a..847456db 100644 --- a/fhevm-engine/Cargo.lock +++ b/fhevm-engine/Cargo.lock @@ -49,7 +49,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand", + "rand 0.8.5", "sha1", "smallvec", "tokio", @@ -221,7 +221,7 @@ dependencies = [ "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -528,7 +528,7 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "k256", - "rand", + "rand 0.8.5", "serde_json", "tempfile", "thiserror 2.0.11", @@ -556,7 +556,7 @@ dependencies = [ "keccak-asm", "paste", "proptest", - "rand", + "rand 0.8.5", "ruint", "rustc-hash", "serde", @@ -738,7 +738,7 @@ dependencies = [ "alloy-serde", "derive_more 1.0.0", "jsonwebtoken", - "rand", + "rand 0.8.5", "serde", "strum", ] @@ -827,7 +827,7 @@ dependencies = [ "alloy-signer", "async-trait", "k256", - "rand", + "rand 0.8.5", "thiserror 2.0.11", ] @@ -854,7 +854,7 @@ dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", - "heck 0.5.0", + "heck", "indexmap 2.7.1", "proc-macro-error2", "proc-macro2", @@ -873,7 +873,7 @@ dependencies = [ "alloy-json-abi", "const-hex", "dunce", - "heck 0.5.0", + "heck", "proc-macro2", "quote", "serde_json", @@ -968,7 +968,7 @@ dependencies = [ "alloy-transport", "futures", "http 1.2.0", - "rustls 0.23.23", + "rustls", "serde_json", "tokio", "tokio-tungstenite", @@ -1206,7 +1206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -1216,7 +1216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", "rayon", ] @@ -1498,9 +1498,9 @@ dependencies = [ "hyperlocal", "log", "pin-project-lite", - "rustls 0.23.23", + "rustls", "rustls-native-certs 0.7.3", - "rustls-pemfile 2.2.0", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_derive", @@ -1684,7 +1684,7 @@ version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.98", @@ -1738,6 +1738,15 @@ dependencies = [ "pulp", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-hex" version = "1.14.0" @@ -1814,7 +1823,7 @@ dependencies = [ "opentelemetry_sdk", "prometheus", "prost", - "rand", + "rand 0.9.0", "rayon", "regex", "scheduler", @@ -1941,7 +1950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -2283,7 +2292,7 @@ dependencies = [ "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -2327,9 +2336,14 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "executor" @@ -2384,7 +2398,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2398,8 +2412,8 @@ dependencies = [ "hex", "paste", "prost", - "rand", - "rand_chacha", + "rand 0.9.0", + "rand_chacha 0.3.1", "serde", "sha3", "strum", @@ -2431,7 +2445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -2781,7 +2795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2861,20 +2875,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "heck" -version = "0.4.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "unicode-segmentation", + "hashbrown 0.15.2", ] [[package]] @@ -3028,13 +3033,13 @@ dependencies = [ "http 1.2.0", "hyper", "hyper-util", - "rustls 0.23.23", + "rustls", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots 0.26.8", + "webpki-roots", ] [[package]] @@ -3524,11 +3529,10 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ - "cc", "pkg-config", "vcpkg", ] @@ -3636,12 +3640,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.4" @@ -3697,16 +3695,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "normalize-path" version = "0.2.1" @@ -3745,7 +3733,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -3974,7 +3962,7 @@ dependencies = [ "once_cell", "opentelemetry", "percent-encoding", - "rand", + "rand 0.8.5", "serde_json", "thiserror 1.0.69", "tokio", @@ -4021,6 +4009,12 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -4218,7 +4212,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -4308,8 +4302,8 @@ dependencies = [ "bitflags", "lazy_static", "num-traits", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -4333,7 +4327,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck", "itertools 0.14.0", "log", "multimap", @@ -4404,7 +4398,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.23", + "rustls", "socket2", "thiserror 2.0.11", "tokio", @@ -4419,10 +4413,10 @@ checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", "getrandom 0.2.15", - "rand", + "rand 0.8.5", "ring", "rustc-hash", - "rustls 0.23.23", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.11", @@ -4467,11 +4461,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "serde", ] +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.17", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -4479,7 +4484,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", ] [[package]] @@ -4491,13 +4506,23 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", +] + [[package]] name = "rand_xorshift" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4625,9 +4650,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.23", + "rustls", "rustls-native-certs 0.8.1", - "rustls-pemfile 2.2.0", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -4643,7 +4668,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.8", + "webpki-roots", "windows-registry", ] @@ -4695,7 +4720,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "signature", "spki", "subtle", @@ -4720,7 +4745,7 @@ dependencies = [ "parity-scale-codec", "primitive-types", "proptest", - "rand", + "rand 0.8.5", "rlp", "ruint-macro", "serde", @@ -4746,7 +4771,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" dependencies = [ - "rand", + "rand 0.8.5", ] [[package]] @@ -4786,17 +4811,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.23" @@ -4806,7 +4820,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki", "subtle", "zeroize", ] @@ -4818,7 +4832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", - "rustls-pemfile 2.2.0", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework 2.11.1", @@ -4836,15 +4850,6 @@ dependencies = [ "security-framework 3.2.0", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -4863,16 +4868,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.102.8" @@ -4959,16 +4954,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sdd" version = "3.0.7" @@ -5143,6 +5128,31 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "serial_test" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "sha1" version = "0.10.6" @@ -5216,7 +5226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -5412,21 +5422,11 @@ dependencies = [ "der", ] -[[package]] -name = "sqlformat" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" -dependencies = [ - "nom", - "unicode_categories", -] - [[package]] name = "sqlx" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" +checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" dependencies = [ "sqlx-core", "sqlx-macros", @@ -5437,70 +5437,64 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" +checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" dependencies = [ - "ahash", - "atoi", - "byteorder", "bytes", "crc", "crossbeam-queue", "either", "event-listener", - "futures-channel", "futures-core", "futures-intrusive", "futures-io", "futures-util", + "hashbrown 0.15.2", "hashlink", - "hex", "indexmap 2.7.1", "log", "memchr", "once_cell", - "paste", "percent-encoding", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", + "rustls", + "rustls-pemfile", "serde", "serde_json", "sha2", "smallvec", - "sqlformat", - "thiserror 1.0.69", + "thiserror 2.0.11", "time", "tokio", "tokio-stream", "tracing", "url", "uuid", - "webpki-roots 0.25.4", + "webpki-roots", ] [[package]] name = "sqlx-macros" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" +checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 1.0.109", + "syn 2.0.98", ] [[package]] name = "sqlx-macros-core" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" +checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" dependencies = [ "dotenvy", "either", - "heck 0.4.1", + "heck", "hex", "once_cell", "proc-macro2", @@ -5512,7 +5506,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 1.0.109", + "syn 2.0.98", "tempfile", "tokio", "url", @@ -5520,12 +5514,12 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" +checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", - "base64 0.21.7", + "base64 0.22.1", "bitflags", "byteorder", "bytes", @@ -5547,7 +5541,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.5", "rsa", "serde", "sha1", @@ -5555,7 +5549,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 1.0.69", + "thiserror 2.0.11", "time", "tracing", "uuid", @@ -5564,12 +5558,12 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" +checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" dependencies = [ "atoi", - "base64 0.21.7", + "base64 0.22.1", "bitflags", "byteorder", "crc", @@ -5577,7 +5571,6 @@ dependencies = [ "etcetera", "futures-channel", "futures-core", - "futures-io", "futures-util", "hex", "hkdf", @@ -5588,14 +5581,14 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.5", "serde", "serde_json", "sha2", "smallvec", "sqlx-core", "stringprep", - "thiserror 1.0.69", + "thiserror 2.0.11", "time", "tracing", "uuid", @@ -5604,9 +5597,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" +checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" dependencies = [ "atoi", "flume", @@ -5619,11 +5612,11 @@ dependencies = [ "log", "percent-encoding", "serde", + "serde_urlencoded", "sqlx-core", "time", "tracing", "url", - "urlencoding", "uuid", ] @@ -5694,7 +5687,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", @@ -5858,7 +5851,7 @@ dependencies = [ "itertools 0.11.0", "paste", "pulp", - "rand_core", + "rand_core 0.6.4", "rayon", "serde", "sha3", @@ -5963,7 +5956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1895354f2c33e7a79b24ac96f08904a396c5ac3ac1bc65587b37cacd7a62e3fa" dependencies = [ "num-bigint", - "rand", + "rand 0.8.5", "rayon", "serde", "sha3", @@ -6145,7 +6138,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.23", + "rustls", "tokio", ] @@ -6181,12 +6174,12 @@ checksum = "be4bf6fecd69fcdede0ec680aaf474cdab988f9de6bc73d3758f0160e3b7025a" dependencies = [ "futures-util", "log", - "rustls 0.23.23", + "rustls", "rustls-pki-types", "tokio", "tokio-rustls", "tungstenite", - "webpki-roots 0.26.8", + "webpki-roots", ] [[package]] @@ -6318,7 +6311,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -6451,6 +6444,8 @@ dependencies = [ "clap", "foundry-compilers", "futures-util", + "rand 0.9.0", + "serial_test", "sqlx", "tokio", "tokio-util", @@ -6476,8 +6471,8 @@ dependencies = [ "http 1.2.0", "httparse", "log", - "rand", - "rustls 0.23.23", + "rand 0.8.5", + "rustls", "rustls-pki-types", "sha1", "thiserror 2.0.11", @@ -6547,12 +6542,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - [[package]] name = "unicode-width" version = "0.2.0" @@ -6565,12 +6554,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - [[package]] name = "untrusted" version = "0.9.0" @@ -6589,12 +6572,6 @@ dependencies = [ "serde", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" @@ -6797,12 +6774,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "webpki-roots" version = "0.26.8" @@ -7141,7 +7112,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive 0.8.17", ] [[package]] @@ -7155,6 +7135,17 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "zerofrom" version = "0.1.5" diff --git a/fhevm-engine/Cargo.toml b/fhevm-engine/Cargo.toml index 3bc8f805..481c1cd4 100644 --- a/fhevm-engine/Cargo.toml +++ b/fhevm-engine/Cargo.toml @@ -16,10 +16,11 @@ daggy = "0.8.0" futures-util = "0.3.31" prometheus = "0.13.4" prost = "0.13" +rand = "0.9.0" rayon = "1.10.0" serde = "1.0.210" sha3 = "0.10.8" -sqlx = { version = "0.7", features = ["runtime-tokio", "tls-rustls", "time", "postgres", "uuid"] } +sqlx = { version = "0.8.3", features = ["runtime-tokio", "tls-rustls", "time", "postgres", "uuid"] } tfhe = { version = "0.10.0", features = ["boolean", "shortint", "integer", "zk-pok", "experimental-force_fft_algo_dif4"] } tokio = { version = "1.38.0", features = ["full"] } tokio-util = "0.7" diff --git a/fhevm-engine/coprocessor/Cargo.toml b/fhevm-engine/coprocessor/Cargo.toml index fce40b59..d3e792c2 100644 --- a/fhevm-engine/coprocessor/Cargo.toml +++ b/fhevm-engine/coprocessor/Cargo.toml @@ -13,6 +13,7 @@ bincode = { workspace = true } clap = { workspace = true } prometheus = { workspace = true } prost = { workspace = true } +rand = { workspace = true } rayon = { workspace = true } sha3 = { workspace = true } sqlx = { workspace = true } @@ -39,7 +40,6 @@ strum = { version = "0.26", features = ["derive"] } tonic-health = "0.12" tonic-types = "0.12" tonic-web = "0.12" -rand = "0.8.5" # local dependencies fhevm-engine-common = { path = "../fhevm-engine-common" } diff --git a/fhevm-engine/coprocessor/build.rs b/fhevm-engine/coprocessor/build.rs index 259ad9f0..408a4b24 100644 --- a/fhevm-engine/coprocessor/build.rs +++ b/fhevm-engine/coprocessor/build.rs @@ -5,6 +5,6 @@ fn main() { tonic_build::configure() .file_descriptor_set_path(out_dir.join("coprocessor_descriptor.bin")) .protoc_arg("--experimental_allow_proto3_optional") - .compile(&["../../proto/coprocessor.proto"], &["../../proto"]) + .compile_protos(&["../../proto/coprocessor.proto"], &["../../proto"]) .unwrap(); } diff --git a/fhevm-engine/executor/build.rs b/fhevm-engine/executor/build.rs index 86adc68b..dcedda21 100644 --- a/fhevm-engine/executor/build.rs +++ b/fhevm-engine/executor/build.rs @@ -4,6 +4,6 @@ fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); tonic_build::configure() .file_descriptor_set_path(out_dir.join("executor_descriptor.bin")) - .compile(&["../../proto/executor.proto"], &["../../proto"]) + .compile_protos(&["../../proto/executor.proto"], &["../../proto"]) .unwrap(); } diff --git a/fhevm-engine/fhevm-db/migrations/20250207092623_verify_proofs.sql b/fhevm-engine/fhevm-db/migrations/20250207092623_verify_proofs.sql index 7f59963e..9456b48e 100644 --- a/fhevm-engine/fhevm-db/migrations/20250207092623_verify_proofs.sql +++ b/fhevm-engine/fhevm-db/migrations/20250207092623_verify_proofs.sql @@ -3,8 +3,10 @@ CREATE TABLE IF NOT EXISTS verify_proofs ( chain_id INTEGER NOT NULL CHECK(chain_id >= 0), contract_address TEXT NOT NULL, user_address TEXT NOT NULL, + input BYTEA, handles BYTEA NOT NULL, - retry_count INTEGER NOT NULL DEFAULT 0 + retry_count INTEGER NOT NULL DEFAULT 0, + verified BOOLEAN NOT NULL DEFAULT false ); -CREATE INDEX IF NOT EXISTS idx_verify_proofs_retry_count ON verify_proofs(retry_count); +CREATE INDEX IF NOT EXISTS idx_verify_proofs_verified_retry ON verify_proofs(verified, retry_count, zk_proof_id); diff --git a/fhevm-engine/fhevm-engine-common/Cargo.toml b/fhevm-engine/fhevm-engine-common/Cargo.toml index 8095ea51..a009b963 100644 --- a/fhevm-engine/fhevm-engine-common/Cargo.toml +++ b/fhevm-engine/fhevm-engine-common/Cargo.toml @@ -9,6 +9,7 @@ license.workspace = true # workspace dependencies anyhow = { workspace = true } bincode = { workspace = true } +rand = { workspace = true } serde = { workspace = true } sha3 = { workspace = true } tfhe = { workspace = true } @@ -18,7 +19,6 @@ tonic = { workspace = true } # crates.io dependencies bigdecimal = "0.4.5" hex = "0.4" -rand = "0.8.5" paste = "1.0.15" rand_chacha = "0.3.1" strum = { version = "0.26", features = ["derive"] } diff --git a/fhevm-engine/fhevm-engine-common/build.rs b/fhevm-engine/fhevm-engine-common/build.rs index d292b8bd..b702872d 100644 --- a/fhevm-engine/fhevm-engine-common/build.rs +++ b/fhevm-engine/fhevm-engine-common/build.rs @@ -4,6 +4,6 @@ fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); tonic_build::configure() .file_descriptor_set_path(out_dir.join("common_descriptor.bin")) - .compile(&["../../proto/common.proto"], &["../../proto"]) + .compile_protos(&["../../proto/common.proto"], &["../../proto"]) .unwrap(); } diff --git a/fhevm-engine/transaction-sender/.sqlx/query-48c4c9a53a5acbd02f349e153927805fd490c42c31e67dffc17426d43671a241.json b/fhevm-engine/transaction-sender/.sqlx/query-c57ce360ee6b9126cf0c49a6749f8b6243f83c1f5be82ad6f57f0ec62a3cfa59.json similarity index 69% rename from fhevm-engine/transaction-sender/.sqlx/query-48c4c9a53a5acbd02f349e153927805fd490c42c31e67dffc17426d43671a241.json rename to fhevm-engine/transaction-sender/.sqlx/query-c57ce360ee6b9126cf0c49a6749f8b6243f83c1f5be82ad6f57f0ec62a3cfa59.json index b107443e..0736071e 100644 --- a/fhevm-engine/transaction-sender/.sqlx/query-48c4c9a53a5acbd02f349e153927805fd490c42c31e67dffc17426d43671a241.json +++ b/fhevm-engine/transaction-sender/.sqlx/query-c57ce360ee6b9126cf0c49a6749f8b6243f83c1f5be82ad6f57f0ec62a3cfa59.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT *\n FROM verify_proofs\n WHERE retry_count < $1\n ORDER BY zk_proof_id\n LIMIT $2", + "query": "SELECT *\n FROM verify_proofs\n WHERE verified = true AND retry_count < $1\n ORDER BY zk_proof_id\n LIMIT $2", "describe": { "columns": [ { @@ -25,13 +25,23 @@ }, { "ordinal": 4, - "name": "handles", + "name": "input", "type_info": "Bytea" }, { "ordinal": 5, + "name": "handles", + "type_info": "Bytea" + }, + { + "ordinal": 6, "name": "retry_count", "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "verified", + "type_info": "Bool" } ], "parameters": { @@ -45,9 +55,11 @@ false, false, false, + true, + false, false, false ] }, - "hash": "48c4c9a53a5acbd02f349e153927805fd490c42c31e67dffc17426d43671a241" + "hash": "c57ce360ee6b9126cf0c49a6749f8b6243f83c1f5be82ad6f57f0ec62a3cfa59" } diff --git a/fhevm-engine/transaction-sender/Cargo.toml b/fhevm-engine/transaction-sender/Cargo.toml index cb636372..ad9902b8 100644 --- a/fhevm-engine/transaction-sender/Cargo.toml +++ b/fhevm-engine/transaction-sender/Cargo.toml @@ -11,6 +11,7 @@ alloy = { workspace = true } anyhow = { workspace = true } clap = { workspace = true } futures-util = { workspace = true } +rand = { workspace = true } sqlx = { workspace = true } tokio = { workspace = true } tokio-util = { workspace = true } @@ -23,3 +24,7 @@ async-trait = "0.1.86" [build-dependencies] # crates.io dependencies foundry-compilers = { version = "0.13.0", features = ["svm-solc"] } + +[dev-dependencies] +# crates.io dependencies +serial_test = "3.2.0" diff --git a/fhevm-engine/transaction-sender/contracts/ZKPoKManager.sol b/fhevm-engine/transaction-sender/contracts/ZKPoKManager.sol index 3cba0f66..bca04806 100644 --- a/fhevm-engine/transaction-sender/contracts/ZKPoKManager.sol +++ b/fhevm-engine/transaction-sender/contracts/ZKPoKManager.sol @@ -6,11 +6,27 @@ contract ZKPoKManager { error CoprocessorHasAlreadySigned(uint256 zkProofId, address signer); + bool alreadySignedRevert; + bool generalRevert; + + constructor(bool _alreadySignedRevert, bool _generalRevert) { + alreadySignedRevert = _alreadySignedRevert; + generalRevert = _generalRevert; + } + function verifyProofResponse( uint256 zkProofId, bytes32[] calldata handles, bytes calldata signature ) public { + if (generalRevert) { + revert("General revert"); + } + + if (alreadySignedRevert) { + revert CoprocessorHasAlreadySigned(zkProofId, msg.sender); + } + emit VerifyProofResponseCalled(zkProofId, handles, signature); } } diff --git a/fhevm-engine/transaction-sender/src/bin/transaction_sender.rs b/fhevm-engine/transaction-sender/src/bin/transaction_sender.rs index 3b3420f3..900fa235 100644 --- a/fhevm-engine/transaction-sender/src/bin/transaction_sender.rs +++ b/fhevm-engine/transaction-sender/src/bin/transaction_sender.rs @@ -67,6 +67,7 @@ fn install_signal_handlers(cancel_token: CancellationToken) -> anyhow::Result<() #[tokio::main] async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt().json().with_level(true).init(); let conf = Conf::parse(); let signer = PrivateKeySigner::from_str(conf.private_key.trim())?; let wallet = EthereumWallet::new(signer.clone()); @@ -101,6 +102,7 @@ async fn main() -> anyhow::Result<()> { error_sleep_initial_secs: conf.error_sleep_initial_secs, error_sleep_max_secs: conf.error_sleep_max_secs, }, + None, ); install_signal_handlers(cancel_token)?; sender.run().await diff --git a/fhevm-engine/transaction-sender/src/lib.rs b/fhevm-engine/transaction-sender/src/lib.rs index 4c623042..af95c53e 100644 --- a/fhevm-engine/transaction-sender/src/lib.rs +++ b/fhevm-engine/transaction-sender/src/lib.rs @@ -1,7 +1,7 @@ mod ops; mod transaction_sender; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ConfigSettings { pub db_url: String, pub db_pool_size: u32, diff --git a/fhevm-engine/transaction-sender/src/ops/add_ciphertexts.rs b/fhevm-engine/transaction-sender/src/ops/add_ciphertext.rs similarity index 82% rename from fhevm-engine/transaction-sender/src/ops/add_ciphertexts.rs rename to fhevm-engine/transaction-sender/src/ops/add_ciphertext.rs index 93e36b30..4afeae0e 100644 --- a/fhevm-engine/transaction-sender/src/ops/add_ciphertexts.rs +++ b/fhevm-engine/transaction-sender/src/ops/add_ciphertext.rs @@ -11,12 +11,12 @@ sol!( ); #[derive(Clone)] -pub struct AddCiphertextsOperation + Clone + 'static> { +pub struct AddCiphertextOperation + Clone + 'static> { ciphertext_storage_address: Address, provider: Arc

, } -impl + Clone + 'static> AddCiphertextsOperation

{ +impl + Clone + 'static> AddCiphertextOperation

{ pub fn new(ciphertext_storage_address: Address, provider: Arc

) -> Self { Self { ciphertext_storage_address, @@ -26,7 +26,7 @@ impl + Clone + 'static> AddCiphertextsOperation

{ } #[async_trait] -impl

TransactionOperation

for AddCiphertextsOperation

+impl

TransactionOperation

for AddCiphertextOperation

where P: alloy::providers::Provider + Clone + 'static, { diff --git a/fhevm-engine/transaction-sender/src/ops/mod.rs b/fhevm-engine/transaction-sender/src/ops/mod.rs index f3d6c839..24791bbc 100644 --- a/fhevm-engine/transaction-sender/src/ops/mod.rs +++ b/fhevm-engine/transaction-sender/src/ops/mod.rs @@ -12,5 +12,5 @@ where async fn execute(&self, db_pool: &Pool) -> anyhow::Result; } -pub(crate) mod add_ciphertexts; -pub(crate) mod verify_proofs; +pub(crate) mod add_ciphertext; +pub(crate) mod verify_proof; diff --git a/fhevm-engine/transaction-sender/src/ops/verify_proofs.rs b/fhevm-engine/transaction-sender/src/ops/verify_proof.rs similarity index 76% rename from fhevm-engine/transaction-sender/src/ops/verify_proofs.rs rename to fhevm-engine/transaction-sender/src/ops/verify_proof.rs index 8020eccb..731d6766 100644 --- a/fhevm-engine/transaction-sender/src/ops/verify_proofs.rs +++ b/fhevm-engine/transaction-sender/src/ops/verify_proof.rs @@ -1,5 +1,6 @@ use super::TransactionOperation; use crate::VERIFY_PROOFS_TARGET; +use alloy::network::TransactionBuilder; use alloy::primitives::{Address, U256}; use alloy::providers::Provider; use alloy::rpc::types::TransactionRequest; @@ -11,7 +12,7 @@ use async_trait::async_trait; use sqlx::{Pool, Postgres}; use std::convert::TryInto; use tokio::task::JoinSet; -use tracing::{error, info}; +use tracing::{debug, error, info}; use ZKPoKManager::ZKPoKManagerErrors; sol! { @@ -30,25 +31,28 @@ sol!( ); #[derive(Clone)] -pub struct VerifyProofsOperation + Clone + 'static> { +pub(crate) struct VerifyProofOperation + Clone + 'static> { zkpok_manager_address: Address, provider: std::sync::Arc

, signer: PrivateKeySigner, database_conf: crate::ConfigSettings, + gas: Option, } -impl + Clone + 'static> VerifyProofsOperation

{ - pub fn new( +impl + Clone + 'static> VerifyProofOperation

{ + pub(crate) fn new( zkpok_manager_address: Address, provider: std::sync::Arc

, signer: PrivateKeySigner, database_conf: crate::ConfigSettings, + gas: Option, ) -> Self { Self { zkpok_manager_address, provider, signer, database_conf, + gas, } } @@ -57,6 +61,7 @@ impl + Clone + 'static> VerifyProofsOper db_pool: &Pool, zk_proof_id: i64, ) -> anyhow::Result<()> { + debug!(target: VERIFY_PROOFS_TARGET, "Removing proof with id {}", zk_proof_id); sqlx::query!( "DELETE FROM verify_proofs WHERE zk_proof_id = $1", zk_proof_id @@ -71,6 +76,7 @@ impl + Clone + 'static> VerifyProofsOper db_pool: &Pool, zk_proof_id: i64, ) -> anyhow::Result<()> { + debug!(target: VERIFY_PROOFS_TARGET, "Updating retry count of proof with id {}", zk_proof_id); sqlx::query!( "UPDATE verify_proofs SET retry_count = retry_count + 1 WHERE zk_proof_id = $1", zk_proof_id @@ -85,6 +91,7 @@ impl + Clone + 'static> VerifyProofsOper db_pool: &Pool, max_retries: u32, ) -> anyhow::Result<()> { + debug!(target: VERIFY_PROOFS_TARGET, "Removing proof with retry count >= {}", max_retries); sqlx::query!( "DELETE FROM verify_proofs WHERE retry_count >= $1", max_retries as i64 @@ -94,17 +101,18 @@ impl + Clone + 'static> VerifyProofsOper Ok(()) } - async fn process_transaction( + async fn process_proof( &self, db_pool: Pool, provider: std::sync::Arc

, txn_request: (i64, impl Into), ) -> anyhow::Result<()> { + info!(target: VERIFY_PROOFS_TARGET, "Processing proof with proof id {}", txn_request.0); let txn_req = txn_request.1.into(); - let transaction = match provider.send_transaction(txn_req).await { + let transaction = match provider.send_transaction(txn_req.clone()).await { Ok(txn) => txn, Err(e) => { - error!(target: VERIFY_PROOFS_TARGET, "Transaction sending failed with error {}", e); + error!(target: VERIFY_PROOFS_TARGET, "Transaction {:?} sending failed with error: {}", txn_req, e); if let Some(ZKPoKManagerErrors::CoprocessorHasAlreadySigned(_)) = e .as_error_resp() .and_then(|payload| payload.as_decoded_error::(true)) @@ -120,10 +128,15 @@ impl + Clone + 'static> VerifyProofsOper } }; - let receipt = match transaction.get_receipt().await { + // Here, we assume we are sending the transaction to a rollup, hence the confirmations of 1. + let receipt = match transaction + .with_required_confirmations(1) + .get_receipt() + .await + { Ok(receipt) => receipt, Err(e) => { - error!(target: VERIFY_PROOFS_TARGET, "Transaction failed with error {}", e); + error!(target: VERIFY_PROOFS_TARGET, "Getting receipt failed with error: {}", e); self.update_retry_count_by_proof_id(&db_pool, txn_request.0) .await?; return Err(anyhow::Error::new(e)); @@ -149,7 +162,7 @@ impl + Clone + 'static> VerifyProofsOper } #[async_trait] -impl

TransactionOperation

for VerifyProofsOperation

+impl

TransactionOperation

for VerifyProofOperation

where P: alloy::providers::Provider + Clone + 'static, { @@ -167,7 +180,7 @@ where let rows = sqlx::query!( "SELECT * FROM verify_proofs - WHERE retry_count < $1 + WHERE verified = true AND retry_count < $1 ORDER BY zk_proof_id LIMIT $2", self.database_conf.verify_proof_resp_max_retries as i64, @@ -175,6 +188,7 @@ where ) .fetch_all(db_pool) .await?; + info!(target: VERIFY_PROOFS_TARGET, "Selected {} rows to process", rows.len()); let maybe_has_more_work = rows.len() == self.database_conf.verify_proof_resp_batch_limit as usize; let mut join_set = JoinSet::new(); @@ -212,22 +226,38 @@ where .signer .sign_hash_sync(&signing_hash) .expect("signing failed"); - let txn_request = ( - row.zk_proof_id, - zkpok_manager - .verifyProofResponse( - U256::from(row.zk_proof_id), - handles, - signature.as_bytes().into(), - ) - .into_transaction_request(), - ); + + let txn_request = if let Some(gas) = self.gas { + ( + row.zk_proof_id, + zkpok_manager + .verifyProofResponse( + U256::from(row.zk_proof_id), + handles, + signature.as_bytes().into(), + ) + .into_transaction_request() + .with_gas_limit(gas), + ) + } else { + ( + row.zk_proof_id, + zkpok_manager + .verifyProofResponse( + U256::from(row.zk_proof_id), + handles, + signature.as_bytes().into(), + ) + .into_transaction_request(), + ) + }; + let db_pool = db_pool.clone(); let provider = self.provider.clone(); let self_clone = self.clone(); join_set.spawn(async move { self_clone - .process_transaction(db_pool, provider, txn_request) + .process_proof(db_pool, provider, txn_request) .await }); } diff --git a/fhevm-engine/transaction-sender/src/transaction_sender.rs b/fhevm-engine/transaction-sender/src/transaction_sender.rs index 16f81b72..57819fd9 100644 --- a/fhevm-engine/transaction-sender/src/transaction_sender.rs +++ b/fhevm-engine/transaction-sender/src/transaction_sender.rs @@ -24,15 +24,17 @@ impl + Clone + 'static> TransactionSender

{ provider: Arc

, cancel_token: CancellationToken, conf: ConfigSettings, + gas: Option ) -> Self { let operations: Vec>> = vec![ - Arc::new(ops::verify_proofs::VerifyProofsOperation::new( + Arc::new(ops::verify_proof::VerifyProofOperation::new( *zkpok_manager_address, provider.clone(), signer.clone(), conf.clone(), + gas )), - Arc::new(ops::add_ciphertexts::AddCiphertextsOperation::new( + Arc::new(ops::add_ciphertext::AddCiphertextOperation::new( *ciphertext_storage_address, provider.clone(), )), @@ -45,6 +47,8 @@ impl + Clone + 'static> TransactionSender

{ } pub async fn run(&self) -> anyhow::Result<()> { + info!(target: TXN_SENDER_TARGET, "Starting transaction sender with: {:?}", self.conf); + let db_pool = sqlx::postgres::PgPoolOptions::new() .max_connections(self.conf.db_pool_size) .connect(&self.conf.db_url) @@ -58,24 +62,34 @@ impl + Clone + 'static> TransactionSender

{ let db_polling_interval_secs = self.conf.db_polling_interval_secs; join_set.spawn({ let sender = self.clone(); + info!(target: TXN_SENDER_TARGET, "Spawning operation loop {}", op_channel); async move { let mut sleep_duration = sender.conf.error_sleep_initial_secs as u64; let mut listener = PgListener::connect_with(&db_pool).await?; listener.listen(&op_channel).await?; loop { + if token.is_cancelled() { + info!(target: TXN_SENDER_TARGET, "Operation {} cancelling", op_channel); + break; + } + match op.execute(&db_pool).await { Err(e) => { error!(target: TXN_SENDER_TARGET, "Operation {} error: {}. Retrying after {} seconds", op_channel, e, sleep_duration); sender.sleep_with_backoff(&mut sleep_duration).await; + continue; } Ok(true) => { // Maybe we have more work to do, don't wait and immediately run the loop again. sender.reset_sleep_duration(&mut sleep_duration); + continue; } Ok(false) => { + // Maybe no more work to do, go and wait for the next notification. sender.reset_sleep_duration(&mut sleep_duration); + tokio::select! { _ = token.cancelled() => { info!(target: TXN_SENDER_TARGET, "Operation {} cancelling", op_channel); @@ -85,7 +99,7 @@ impl + Clone + 'static> TransactionSender

{ match notif { Ok(Some(_)) => { debug!(target: TXN_SENDER_TARGET, - "Operation {} received notification, rechecking work", op_channel); + "Operation {} received notification, rechecking for work", op_channel); }, Ok(None) => { debug!(target: TXN_SENDER_TARGET, @@ -103,7 +117,7 @@ impl + Clone + 'static> TransactionSender

{ } _ = tokio::time::sleep(Duration::from_secs(db_polling_interval_secs.into())) => { debug!(target: TXN_SENDER_TARGET, - "Operation {} timeout reached, rechecking work", op_channel); + "Operation {} timeout reached, rechecking for work", op_channel); } } } diff --git a/fhevm-engine/transaction-sender/tests/common.rs b/fhevm-engine/transaction-sender/tests/common.rs new file mode 100644 index 00000000..0be51b77 --- /dev/null +++ b/fhevm-engine/transaction-sender/tests/common.rs @@ -0,0 +1,54 @@ +use alloy::{signers::local::PrivateKeySigner, sol}; +use sqlx::{postgres::PgPoolOptions, Pool, Postgres}; +use tokio_util::sync::CancellationToken; +use tracing::Level; +use transaction_sender::ConfigSettings; + +sol!( + #[sol(rpc)] + ZKPoKManager, + "artifacts/ZKPoKManager.sol/ZKPoKManager.json" +); + +sol!( + #[sol(rpc)] + CiphertextStorage, + "artifacts/CiphertextStorage.sol/CiphertextStorage.json" +); + +pub struct TestEnvironment { + pub signer: PrivateKeySigner, + pub conf: ConfigSettings, + pub cancel_token: CancellationToken, + pub db_pool: Pool, +} + +impl TestEnvironment { + pub async fn new() -> anyhow::Result { + let _ = tracing_subscriber::fmt() + .json() + .with_level(true) + .with_max_level(Level::DEBUG) + .with_test_writer() + .try_init(); + + let conf = ConfigSettings::default(); + + let db_pool = PgPoolOptions::new() + .max_connections(1) + .connect(&conf.db_url) + .await?; + + // Delete all proofs from the database. + sqlx::query!("TRUNCATE verify_proofs",) + .execute(&db_pool) + .await?; + + Ok(Self { + signer: PrivateKeySigner::random(), + conf: conf, + cancel_token: CancellationToken::new(), + db_pool, + }) + } +} diff --git a/fhevm-engine/transaction-sender/tests/integration_test.rs b/fhevm-engine/transaction-sender/tests/integration_test.rs deleted file mode 100644 index 910f223d..00000000 --- a/fhevm-engine/transaction-sender/tests/integration_test.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::sync::Arc; - -use alloy::{providers::ProviderBuilder, signers::local::PrivateKeySigner, sol}; -use futures_util::StreamExt; -use tokio_util::sync::CancellationToken; -use transaction_sender::{ConfigSettings, TransactionSender}; - -sol!( - #[sol(rpc)] - ZKPoKManager, - "artifacts/ZKPoKManager.sol/ZKPoKManager.json" -); - -sol!( - #[sol(rpc)] - CiphertextStorage, - "artifacts/CiphertextStorage.sol/CiphertextStorage.json" -); - -#[tokio::test] -async fn verify_proof_response() -> anyhow::Result<()> { - let signer = PrivateKeySigner::random(); - let provider = Arc::new(ProviderBuilder::new().on_anvil_with_wallet()); - let zkpok_manager = ZKPoKManager::deploy(&provider).await?; - let ciphertext_storage = CiphertextStorage::deploy(&provider).await?; - let cancel_token = CancellationToken::new(); - let conf = ConfigSettings::default(); - let txn_sender = TransactionSender::new( - &zkpok_manager.address(), - &ciphertext_storage.address(), - signer.clone(), - provider.clone(), - cancel_token.clone(), - conf.clone(), - ); - - let event_filter = zkpok_manager - .VerifyProofResponseCalled_filter() - .watch() - .await?; - - let run_handle = tokio::spawn(async move { txn_sender.run().await }); - - let db_pool = sqlx::postgres::PgPoolOptions::new() - .max_connections(1) - .connect(&conf.db_url) - .await?; - - sqlx::query!( - "INSERT INTO verify_proofs (zk_proof_id, chain_id, contract_address, user_address, handles) - VALUES ($1, $2, $3, $4, $5)", - 1, - 42, - signer.address().to_string(), - signer.address().to_string(), - &[1u8; 64], - ) - .execute(&db_pool) - .await?; - - let _event = event_filter - .into_stream() - .take(1) - .collect::>() - .await - .first() - .unwrap() - .clone() - .unwrap(); - - cancel_token.cancel(); - run_handle.await??; - Ok(()) -} diff --git a/fhevm-engine/transaction-sender/tests/verify_proof_tests.rs b/fhevm-engine/transaction-sender/tests/verify_proof_tests.rs new file mode 100644 index 00000000..63a6164c --- /dev/null +++ b/fhevm-engine/transaction-sender/tests/verify_proof_tests.rs @@ -0,0 +1,351 @@ +use alloy::primitives::FixedBytes; +use alloy::providers::{Provider, WalletProvider}; +use alloy::{primitives::U256, sol_types::eip712_domain}; +use alloy::{providers::ProviderBuilder, signers::SignerSync, sol, sol_types::SolStruct}; +use common::{CiphertextStorage, TestEnvironment, ZKPoKManager}; +use futures_util::StreamExt; +use rand::random; +use serial_test::serial; +use std::sync::Arc; +use std::time::Duration; +use tokio::time::sleep; +use transaction_sender::TransactionSender; + +mod common; + +#[tokio::test] +#[serial(db)] +async fn verify_proof_response_success() -> anyhow::Result<()> { + sol! { + struct VerifyProofSignatureData { + bytes32[] handles; + address userAddress; + address contractAddress; + uint256 chainId; + } + } + + let env = TestEnvironment::new().await?; + let provider = Arc::new(ProviderBuilder::new().on_anvil_with_wallet()); + let zkpok_manager = ZKPoKManager::deploy(&provider, false, false).await?; + let ciphertext_storage = CiphertextStorage::deploy(&provider).await?; + let txn_sender = TransactionSender::new( + &zkpok_manager.address(), + &ciphertext_storage.address(), + env.signer.clone(), + provider.clone(), + env.cancel_token.clone(), + env.conf.clone(), + None, + ); + + let event_filter = zkpok_manager + .VerifyProofResponseCalled_filter() + .watch() + .await?; + + let proof_id: u32 = random(); + + let run_handle = tokio::spawn(async move { txn_sender.run().await }); + + let event_handle = tokio::spawn(async move { + event_filter + .into_stream() + .take(1) + .collect::>() + .await + .first() + .unwrap() + .clone() + .unwrap() + }); + + // Insert a proof into the database. + sqlx::query!( + "INSERT INTO verify_proofs (zk_proof_id, chain_id, contract_address, user_address, handles, verified) + VALUES ($1, $2, $3, $4, $5, true)", + proof_id as i64, + 42, + env.signer.address().to_string(), + env.signer.address().to_string(), + &[1u8; 64], + ) + .execute(&env.db_pool) + .await?; + + // Notify the sender to process the proof. + sqlx::query!( + "SELECT pg_notify($1, '')", + env.conf.verify_proof_resp_db_channel + ) + .execute(&env.db_pool) + .await?; + + let event = event_handle.await?; + + let expected_proof_id = U256::from(proof_id); + let expected_handles: Vec> = vec![FixedBytes([1u8; 32]), FixedBytes([1u8; 32])]; + let domain = eip712_domain! { + name: "InputVerifier", + version: "1", + chain_id: 42, + verifying_contract: *zkpok_manager.address(), + }; + let signing_hash = VerifyProofSignatureData { + handles: expected_handles.clone(), + userAddress: env.signer.address(), + contractAddress: env.signer.address(), + chainId: U256::from(42), + } + .eip712_signing_hash(&domain); + let expected_sig = env.signer.sign_hash_sync(&signing_hash)?; + + // Make sure data in the event is correct. + assert_eq!(event.0._0, expected_proof_id); + assert_eq!(event.0._1, expected_handles); + assert_eq!(event.0._2.as_ref(), expected_sig.as_bytes()); + + // Make sure the proof is removed from the database. + loop { + let rows = sqlx::query!( + "SELECT * + FROM verify_proofs + WHERE zk_proof_id = $1", + proof_id as i64, + ) + .fetch_all(&env.db_pool) + .await?; + if rows.is_empty() { + break; + } + sleep(Duration::from_millis(500)).await; + } + + env.cancel_token.cancel(); + run_handle.await??; + Ok(()) +} + +#[tokio::test] +#[serial(db)] +async fn verify_proof_response_reversal_already_signed() -> anyhow::Result<()> { + let env = TestEnvironment::new().await?; + let provider = Arc::new(ProviderBuilder::new().on_anvil_with_wallet()); + let zkpok_manager = ZKPoKManager::deploy(&provider, true, false).await?; + let ciphertext_storage = CiphertextStorage::deploy(&provider).await?; + let txn_sender = TransactionSender::new( + &zkpok_manager.address(), + &ciphertext_storage.address(), + env.signer.clone(), + provider.clone(), + env.cancel_token.clone(), + env.conf.clone(), + None, + ); + + let proof_id: u32 = random(); + + let run_handle = tokio::spawn(async move { txn_sender.run().await }); + + // Record initial transaction count. + let initial_tx_count = provider + .get_transaction_count(provider.default_signer_address()) + .await?; + + // Insert a proof into the database. + sqlx::query!( + "INSERT INTO verify_proofs (zk_proof_id, chain_id, contract_address, user_address, handles, verified) + VALUES ($1, $2, $3, $4, $5, true)", + proof_id as i64, + 42, + env.signer.address().to_string(), + env.signer.address().to_string(), + &[1u8; 64], + ) + .execute(&env.db_pool) + .await?; + + // Notify the sender to process the proof. + sqlx::query!( + "SELECT pg_notify($1, '')", + env.conf.verify_proof_resp_db_channel + ) + .execute(&env.db_pool) + .await?; + + // Make sure the proof is removed from the database. + loop { + let rows = sqlx::query!( + "SELECT * + FROM verify_proofs + WHERE zk_proof_id = $1", + proof_id as i64, + ) + .fetch_all(&env.db_pool) + .await?; + if rows.is_empty() { + break; + } + sleep(Duration::from_millis(500)).await; + } + + // Verify that no transaction has been sent. + let final_tx_count = provider + .get_transaction_count(provider.default_signer_address()) + .await?; + assert_eq!( + final_tx_count, initial_tx_count, + "Expected no new transaction to be sent" + ); + + env.cancel_token.cancel(); + run_handle.await??; + Ok(()) +} + +#[tokio::test] +#[serial(db)] +async fn verify_proof_response_other_reversal_gas_estimation() -> anyhow::Result<()> { + let env = TestEnvironment::new().await?; + let provider = Arc::new(ProviderBuilder::new().on_anvil_with_wallet()); + let zkpok_manager = ZKPoKManager::deploy(&provider, false, true).await?; + let ciphertext_storage = CiphertextStorage::deploy(&provider).await?; + let txn_sender = TransactionSender::new( + &zkpok_manager.address(), + &ciphertext_storage.address(), + env.signer.clone(), + provider.clone(), + env.cancel_token.clone(), + env.conf.clone(), + None, + ); + + let proof_id: u32 = random(); + + let run_handle = tokio::spawn(async move { txn_sender.run().await }); + + // Insert a proof into the database. + sqlx::query!( + "INSERT INTO verify_proofs (zk_proof_id, chain_id, contract_address, user_address, handles, verified) + VALUES ($1, $2, $3, $4, $5, true)", + proof_id as i64, + 42, + env.signer.address().to_string(), + env.signer.address().to_string(), + &[1u8; 64], + ) + .execute(&env.db_pool) + .await?; + + // Notify the sender to process the proof. + sqlx::query!( + "SELECT pg_notify($1, '')", + env.conf.verify_proof_resp_db_channel + ) + .execute(&env.db_pool) + .await?; + + // Make sure the proof retry count is incremented. + // + // Note this is a racy test, because the retry count is incremented by the transaction sender and it might + // get to a point where retry count reaches max retries - then, transaction sender gives up and deletes the entry. + loop { + let rows = sqlx::query!( + "SELECT * + FROM verify_proofs + WHERE zk_proof_id = $1", + proof_id as i64, + ) + .fetch_all(&env.db_pool) + .await?; + assert_eq!(rows.len(), 1); + if rows.first().unwrap().retry_count > 0 { + break; + } + sleep(Duration::from_millis(500)).await; + } + + env.cancel_token.cancel(); + run_handle.await??; + + // Make sure the entry is removed at the end of the test. + sqlx::query("DELETE FROM verify_proofs WHERE zk_proof_id = $1") + .bind(proof_id as i64) + .execute(&env.db_pool) + .await?; + Ok(()) +} + +#[tokio::test] +#[serial(db)] +async fn verify_proof_response_other_reversal_receipt() -> anyhow::Result<()> { + let env = TestEnvironment::new().await?; + let provider = Arc::new(ProviderBuilder::new().on_anvil_with_wallet()); + let zkpok_manager = ZKPoKManager::deploy(&provider, false, true).await?; + let ciphertext_storage = CiphertextStorage::deploy(&provider).await?; + // Create the sender with a gas limit such that no gas estimation is done, forcing failure at receipt (after the txn has been sent). + let txn_sender = TransactionSender::new( + &zkpok_manager.address(), + &ciphertext_storage.address(), + env.signer.clone(), + provider.clone(), + env.cancel_token.clone(), + env.conf.clone(), + Some(1_000_000), + ); + + let proof_id: u32 = random(); + + let run_handle = tokio::spawn(async move { txn_sender.run().await }); + + // Insert a proof into the database. + sqlx::query!( + "INSERT INTO verify_proofs (zk_proof_id, chain_id, contract_address, user_address, handles, verified) + VALUES ($1, $2, $3, $4, $5, true)", + proof_id as i64, + 42, + env.signer.address().to_string(), + env.signer.address().to_string(), + &[1u8; 64], + ) + .execute(&env.db_pool) + .await?; + + // Notify the sender to process the proof. + sqlx::query!( + "SELECT pg_notify($1, '')", + env.conf.verify_proof_resp_db_channel + ) + .execute(&env.db_pool) + .await?; + + // Make sure the proof retry count is incremented. + // + // Note this is a racy test, because the retry count is incremented by the transaction sender and it might + // get to a point where retry count reaches max retries - then, transaction sender gives up and deletes the entry. + loop { + let rows = sqlx::query!( + "SELECT * + FROM verify_proofs + WHERE zk_proof_id = $1", + proof_id as i64, + ) + .fetch_all(&env.db_pool) + .await?; + assert_eq!(rows.len(), 1); + if rows.first().unwrap().retry_count > 0 { + break; + } + sleep(Duration::from_millis(500)).await; + } + + env.cancel_token.cancel(); + run_handle.await??; + + // Make sure the entry is removed at the end of the test. + sqlx::query("DELETE FROM verify_proofs WHERE zk_proof_id = $1") + .bind(proof_id as i64) + .execute(&env.db_pool) + .await?; + Ok(()) +}