From 90d33f92693b647c2d4076d96689be8a2d330810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=B3=CE=BB?= Date: Tue, 5 Nov 2024 10:56:42 +0700 Subject: [PATCH] Add EVM Tests (#170) * Enable testing of evm event subscription * Add foundry to CI * Format code * Move to start * Add bash script to build test fixture contracts * Use the base script to run tests * Add solc install to GA * Remove whitespace * Add information on prerequisites * Test event content * Fix display bug --- .github/workflows/rust-ci.yml | 16 +- package.json | 2 +- packages/ciphernode/Cargo.lock | 330 ++++++++++++------ packages/ciphernode/Cargo.toml | 2 +- packages/ciphernode/README.md | 33 +- packages/ciphernode/core/src/events.rs | 38 +- .../ciphernode/evm/scripts/build_fixtures.sh | 7 + .../evm/src/ciphernode_registry_sol.rs | 11 +- packages/ciphernode/evm/src/enclave_sol.rs | 6 +- .../ciphernode/evm/src/enclave_sol_reader.rs | 7 +- .../ciphernode/evm/src/enclave_sol_writer.rs | 15 +- packages/ciphernode/evm/src/event_reader.rs | 55 ++- packages/ciphernode/evm/src/helpers.rs | 64 ++-- packages/ciphernode/evm/src/lib.rs | 2 +- .../ciphernode/evm/src/registry_filter_sol.rs | 13 +- packages/ciphernode/evm/tests/evm_reader.rs | 80 +++++ .../ciphernode/evm/tests/fixtures/.gitignore | 2 + .../evm/tests/fixtures/emit_logs.sol | 21 ++ packages/ciphernode/scripts/test.sh | 7 + 19 files changed, 522 insertions(+), 189 deletions(-) create mode 100755 packages/ciphernode/evm/scripts/build_fixtures.sh create mode 100644 packages/ciphernode/evm/tests/evm_reader.rs create mode 100644 packages/ciphernode/evm/tests/fixtures/.gitignore create mode 100644 packages/ciphernode/evm/tests/fixtures/emit_logs.sol create mode 100755 packages/ciphernode/scripts/test.sh diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 1fdf5d12..7a3aef89 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -18,7 +18,17 @@ jobs: with: toolchain: 1.81.0 override: true - + + # We must install foundry in order to be able to test anvil + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Install solc + run: | + sudo add-apt-repository ppa:ethereum/ethereum \ + && sudo apt-get update -y \ + && sudo apt-get install -y solc + # We need to setup node in order to compile the hardhat contracts to get the artifacts - name: "Setup node" uses: actions/setup-node@v2 @@ -41,6 +51,4 @@ jobs: run: cd ./packages/ciphernode && cargo fmt -- --check - name: Run tests - run: | - cd ./packages/ciphernode/ - cargo test + run: "yarn ciphernode:test" diff --git a/package.json b/package.json index d4fc3c7a..b60e1886 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "ciphernode:lint": "cd packages/ciphernode && cargo fmt -- --check", "ciphernode:add": "cd packages/evm && yarn ciphernode:add", "ciphernode:remove": "cd packages/evm && yarn ciphernode:remove", - "ciphernode:test": "cd packages/ciphernode && cargo test", + "ciphernode:test": "cd packages/ciphernode && ./scripts/test.sh", "ciphernode:build": "cd packages/ciphernode && cargo build --release", "preciphernode:build": "yarn evm:compile", "committee:new": "cd packages/evm && yarn committee:new", diff --git a/packages/ciphernode/Cargo.lock b/packages/ciphernode/Cargo.lock index b85c21be..e94bcb33 100644 --- a/packages/ciphernode/Cargo.lock +++ b/packages/ciphernode/Cargo.lock @@ -131,6 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -153,9 +154,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37d89f69cb43901949ba29307ada8b9e3b170f94057ad4c04d6fd169d24d65f" +checksum = "ea8ebf106e84a1c37f86244df7da0c7587e697b71a0d565cce079449b85ac6f8" dependencies = [ "alloy-consensus", "alloy-contract", @@ -163,6 +164,7 @@ dependencies = [ "alloy-eips", "alloy-genesis", "alloy-network", + "alloy-node-bindings", "alloy-provider", "alloy-pubsub", "alloy-rpc-client", @@ -188,33 +190,35 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1468e3128e07c7afe4ff13c17e8170c330d12c322f8924b8bf6986a27e0aad3d" +checksum = "41ed961a48297c732a5d97ee321aa8bb5009ecadbcb077d8bec90cb54e651629" dependencies = [ "alloy-eips", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", "alloy-serde", + "auto_impl", "c-kzg", + "derive_more 1.0.0", "serde", ] [[package]] name = "alloy-contract" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335d62de1a887f1b780441f8a3037f39c9fb26839cc9acd891c9b80396145cd5" +checksum = "460ab80ce4bda1c80bcf96fe7460520476f2c7b734581c6567fac2708e2a60ef" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-network", "alloy-network-primitives", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-provider", "alloy-pubsub", "alloy-rpc-types-eth", - "alloy-sol-types 0.8.3", + "alloy-sol-types 0.8.10", "alloy-transport", "futures", "futures-util", @@ -223,26 +227,27 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b095eb0533144b4497e84a9cc3e44a5c2e3754a3983c0376a55a2f9183a53e" +checksum = "b72bf30967a232bec83809bea1623031f6285a013096229330c68c406192a4ca" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", - "alloy-primitives 0.8.3", - "alloy-sol-types 0.8.3", + "alloy-primitives 0.8.10", + "alloy-rlp", + "alloy-sol-types 0.8.10", ] [[package]] name = "alloy-dyn-abi" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4004925bff5ba0a11739ae84dbb6601a981ea692f3bd45b626935ee90a6b8471" +checksum = "f5228b189b18b85761340dc9eaac0141148a8503657b36f9bc3a869413d987ca" dependencies = [ "alloy-json-abi", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-sol-type-parser", - "alloy-sol-types 0.8.3", + "alloy-sol-types 0.8.10", "const-hex", "itoa", "serde", @@ -256,32 +261,33 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.1.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d319bb544ca6caeab58c39cea8921c55d924d4f68f2c60f24f914673f9a74a" +checksum = "64ffc577390ce50234e02d841214b3dc0bea6aaaae8e04bbf3cb82e9a45da9eb" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", + "derive_more 1.0.0", "k256", "serde", ] [[package]] name = "alloy-eips" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c35df7b972b06f1b2f4e8b7a53328522fa788054a9d3e556faf2411c5a51d5a" +checksum = "b69e06cf9c37be824b9d26d6d101114fdde6af0c87de2828b414c05c4b3daa71" dependencies = [ "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", "alloy-serde", "c-kzg", @@ -293,22 +299,22 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7210f9206c0fa2a83c824cf8cb6c962126bc9fdc4f41ade1932f14150ef5f6" +checksum = "dde15e14944a88bd6a57d325e9a49b75558746fe16aaccc79713ae50a6a9574c" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-serde", "serde", ] [[package]] name = "alloy-json-abi" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9996daf962fd0a90d3c93b388033228865953b92de7bb1959b891d78750a4091" +checksum = "31a0f0d51db8a1a30a4d98a9f90e090a94c8f44cb4d9eafc7e03aa6d00aae984" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-sol-type-parser", "serde", "serde_json", @@ -316,12 +322,12 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8866562186d237f1dfeaf989ef941a24764f764bf5c33311e37ead3519c6a429" +checksum = "af5979e0d5a7bf9c7eb79749121e8256e59021af611322aee56e77e20776b4b3" dependencies = [ - "alloy-primitives 0.8.3", - "alloy-sol-types 0.8.3", + "alloy-primitives 0.8.10", + "alloy-sol-types 0.8.10", "serde", "serde_json", "thiserror", @@ -330,19 +336,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe714e233f9eaf410de95a9af6bcd05d3a7f8c8de7a0817221e95a6b642a080" +checksum = "204237129086ce5dc17a58025e93739b01b45313841f98fa339eb1d780511e57" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network-primitives", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rpc-types-eth", "alloy-serde", "alloy-signer", - "alloy-sol-types 0.8.3", + "alloy-sol-types 0.8.10", "async-trait", "auto_impl", "futures-utils-wasm", @@ -351,16 +357,34 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c5a38117974c5776a45e140226745a0b664f79736aa900995d8e4121558e064" +checksum = "514f70ee2a953db21631cd817b13a1571474ec77ddc03d47616d5e8203489fde" dependencies = [ + "alloy-consensus", "alloy-eips", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-serde", "serde", ] +[[package]] +name = "alloy-node-bindings" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27444ea67d360508753022807cdd0b49a95c878924c9c5f8f32668b7d7768245" +dependencies = [ + "alloy-genesis", + "alloy-primitives 0.8.10", + "k256", + "rand", + "serde_json", + "tempfile", + "thiserror", + "tracing", + "url", +] + [[package]] name = "alloy-primitives" version = "0.6.4" @@ -385,31 +409,37 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411aff151f2a73124ee473708e82ed51b2535f68928b6a1caa8bc1246ae6f7cd" +checksum = "8edae627382349b56cd6a7a2106f4fd69b243a9233e560c55c2e03cabb7e1d3c" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more 1.0.0", + "foldhash", + "hashbrown 0.15.0", "hex-literal", + "indexmap", "itoa", "k256", "keccak-asm", + "paste", "proptest", "rand", "ruint", + "rustc-hash", "serde", + "sha3", "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65633d6ef83c3626913c004eaf166a6dd50406f724772ea8567135efd6dc5d3" +checksum = "4814d141ede360bb6cd1b4b064f1aab9de391e7c4d0d4d50ac89ea4bc1e25fbd" dependencies = [ "alloy-chains", "alloy-consensus", @@ -417,10 +447,14 @@ dependencies = [ "alloy-json-rpc", "alloy-network", "alloy-network-primitives", - "alloy-primitives 0.8.3", + "alloy-node-bindings", + "alloy-primitives 0.8.10", "alloy-pubsub", "alloy-rpc-client", + "alloy-rpc-types-anvil", "alloy-rpc-types-eth", + "alloy-signer", + "alloy-signer-local", "alloy-transport", "alloy-transport-http", "alloy-transport-ipc", @@ -432,24 +466,27 @@ dependencies = [ "futures", "futures-utils-wasm", "lru", + "parking_lot 0.12.3", "pin-project", "reqwest", + "schnellru", "serde", "serde_json", "thiserror", "tokio", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-pubsub" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b9f5e85120aab30b8da23354592f7bd2b208d33d3204ffa1d44ac2e3dd5691" +checksum = "96ba46eb69ddf7a9925b81f15229cb74658e6eebe5dd30a5b74e2cd040380573" dependencies = [ "alloy-json-rpc", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-transport", "bimap", "futures", @@ -485,12 +522,12 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fc328bb5d440599ba1b5aa44c0b9ab0625fbc3a403bb5ee94ed4a01ba23e07" +checksum = "7fc2bd1e7403463a5f2c61e955bcc9d3072b63aa177442b0f9aa6a6d22a941e3" dependencies = [ "alloy-json-rpc", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-pubsub", "alloy-transport", "alloy-transport-http", @@ -506,70 +543,86 @@ dependencies = [ "tower 0.5.1", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-rpc-types" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22045187a5ebf5b2af3f8b6831b66735b6556c5750ec5790aeeb45935260c1c2" +checksum = "eea9bf1abdd506f985a53533f5ac01296bcd6102c5e139bbc5d40bc468d2c916" dependencies = [ + "alloy-primitives 0.8.10", "alloy-rpc-types-engine", "alloy-rpc-types-eth", "alloy-serde", "serde", ] +[[package]] +name = "alloy-rpc-types-anvil" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382fc63fb0cf3e02818d547b80cb66cc49a31f8803d0c328402b2008bc13650" +dependencies = [ + "alloy-primitives 0.8.10", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-rpc-types-engine" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c031a91e94a39f928244bc837c953817be5b8cc61759e1a9123b3abd17560dd" +checksum = "886d22d41992287a235af2f3af4299b5ced2bcafb81eb835572ad35747476946" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", + "alloy-serde", "derive_more 1.0.0", + "serde", + "strum", ] [[package]] name = "alloy-rpc-types-eth" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a59b1d7c86e0a653e7f3d29954f6de5a2878d8cfd1f010ff93be5c2c48cd3b1" +checksum = "00b034779a4850b4b03f5be5ea674a1cf7d746b2da762b34d1860ab45e48ca27" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-network-primitives", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-rlp", "alloy-serde", - "alloy-sol-types 0.8.3", + "alloy-sol-types 0.8.10", + "derive_more 1.0.0", "itertools 0.13.0", "serde", "serde_json", - "thiserror", ] [[package]] name = "alloy-serde" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51db8a6428a2159e01b7a43ec7aac801edd0c4db1d4de06f310c288940f16fd3" +checksum = "028e72eaa9703e4882344983cfe7636ce06d8cce104a78ea62fd19b46659efc4" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "serde", "serde_json", ] [[package]] name = "alloy-signer" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebc1760c13592b7ba3fcd964abba546b8d6a9f10d15e8d92a8263731be33f36" +checksum = "592c185d7100258c041afac51877660c7bf6213447999787197db4842f0e938e" dependencies = [ - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "async-trait", "auto_impl", "elliptic-curve", @@ -579,13 +632,13 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e250010dce0e3caf6a6033e809718e5921391d937d1cbbcffe52653b37cc63" +checksum = "6614f02fc1d5b079b2a4a5320018317b506fd0a6d67c1fd5542a71201724986c" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 0.8.3", + "alloy-primitives 0.8.10", "alloy-signer", "async-trait", "k256", @@ -613,9 +666,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0458ccb02a564228fcd76efb8eb5a520521a8347becde37b402afec9a1b83859" +checksum = "841eabaa4710f719fddbc24c95d386eae313f07e6da4babc25830ee37945be0c" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -627,9 +680,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc65475025fc1e84bf86fc840f04f63fcccdcf3cf12053c99918e4054dfbc69" +checksum = "6672337f19d837b9f7073c45853aeb528ed9f7dd6a4154ce683e9e5cb7794014" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -640,15 +693,15 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.72", - "syn-solidity 0.8.3", + "syn-solidity 0.8.10", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed10f0715a0b69fde3236ff3b9ae5f6f7c97db5a387747100070d3016b9266b" +checksum = "0dff37dd20bfb118b777c96eda83b2067f4226d2644c5cfa00187b3bc01770ba" dependencies = [ "alloy-json-abi", "const-hex", @@ -658,14 +711,14 @@ dependencies = [ "quote", "serde_json", "syn 2.0.72", - "syn-solidity 0.8.3", + "syn-solidity 0.8.10", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edae8ea1de519ccba896b6834dec874230f72fe695ff3c9c118e90ec7cff783" +checksum = "5b853d42292dbb159671a3edae3b2750277ff130f32b726fe07dc2b17aa6f2b5" dependencies = [ "serde", "winnow", @@ -685,22 +738,22 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eb88e4da0a1b697ed6a9f811fdba223cf4d5c21410804fd1707836af73a462b" +checksum = "aa828bb1b9a6dc52208fbb18084fb9ce2c30facc2bfda6a5d922349b4990354f" dependencies = [ "alloy-json-abi", - "alloy-primitives 0.8.3", - "alloy-sol-macro 0.8.3", + "alloy-primitives 0.8.10", + "alloy-sol-macro 0.8.10", "const-hex", "serde", ] [[package]] name = "alloy-transport" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5dc4e902f1860d54952446d246ac05386311ad61030a2b906ae865416d36e0" +checksum = "be77579633ebbc1266ae6fd7694f75c408beb1aeb6865d0b18f22893c265a061" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -713,13 +766,14 @@ dependencies = [ "tower 0.5.1", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-transport-http" -version = "0.3.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1742b94bb814f1ca6b322a6f9dd38a0252ff45a3119e40e888fb7029afa500ce" +checksum = "91fd1a5d0827939847983b46f2f79510361f901dc82f8e3c38ac7397af142c6e" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -732,9 +786,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa02db8751f9c0c37caf8c38ad3eb7aa1cfb09cfea3451a13aacaf06846c7a5" +checksum = "8073d1186bfeeb8fbdd1292b6f1a0731f3aed8e21e1463905abfae0b96a887a6" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -751,9 +805,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.3.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5c4a0929479bcb85a2df628c01173618a71c807b2f499939a236dbde5d008" +checksum = "61f27837bb4a1d6c83a28231c94493e814882f0e9058648a97e908a5f3fc9fcf" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -1864,7 +1918,7 @@ checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", "crossbeam-utils", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core 0.9.10", @@ -2470,6 +2524,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2767,6 +2827,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "hashbrown" version = "0.14.5" @@ -2777,6 +2843,16 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "foldhash", + "serde", +] + [[package]] name = "heck" version = "0.4.1" @@ -3135,12 +3211,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", + "serde", ] [[package]] @@ -3267,6 +3344,15 @@ dependencies = [ "signature", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "keccak-asm" version = "0.1.3" @@ -3942,7 +4028,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -5010,6 +5096,7 @@ dependencies = [ "libc", "rand_chacha", "rand_core", + "serde", ] [[package]] @@ -5489,6 +5576,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -5641,6 +5739,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "sha3-asm" version = "0.1.3" @@ -5884,9 +5992,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b95156f8b577cb59dc0b1df15c6f29a10afc5f8a7ac9786b0b5c68c19149278" +checksum = "16320d4a2021ba1a32470b3759676114a918885e9800e68ad60f2c67969fba62" dependencies = [ "paste", "proc-macro2", @@ -6167,9 +6275,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", @@ -6321,9 +6429,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" dependencies = [ "byteorder", "bytes", @@ -6604,6 +6712,20 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasmtimer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ed9d8b15c7fb594d72bfb4b5a276f3d2029333cd93a932f376f5937f6f80ee" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.12.3", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "web-sys" version = "0.3.69" diff --git a/packages/ciphernode/Cargo.toml b/packages/ciphernode/Cargo.toml index e8ff4fb1..1fcc7534 100644 --- a/packages/ciphernode/Cargo.toml +++ b/packages/ciphernode/Cargo.toml @@ -21,7 +21,7 @@ members = [ [workspace.dependencies] actix = "0.13.5" aes-gcm = "0.10.3" -alloy = { version = "0.3.3", features = ["full"] } +alloy = { version = "0.5.2", features = ["full", "node-bindings"] } alloy-primitives = { version = "0.6", default-features = false, features = [ "rlp", "serde", diff --git a/packages/ciphernode/README.md b/packages/ciphernode/README.md index 29e2007b..cb035f5b 100644 --- a/packages/ciphernode/README.md +++ b/packages/ciphernode/README.md @@ -1,3 +1,29 @@ +# Prerequisites + +Tested prerequisite versions: + +``` +$ rustc --version +rustc 1.81.0 (eeb90cda1 2024-09-04) +``` + +We need `solc` available for compiling contract fixtures that are used under test + +``` +$ solc --version +solc, the solidity compiler commandline interface +Version: 0.8.21+commit.d9974bed.Linux.g++ +``` + +We need foundry's `anvil` to test our evm facing rust code: + +``` +anvil --version +anvil 0.2.0 (9501589 2024-10-30T00:22:24.181391729Z) +``` + +Note some older versions of `anvil` are not compatible and can cause errors. + # E3 Requested ```mermaid @@ -9,8 +35,8 @@ sequenceDiagram participant KS as Keyshare participant PKA as PublicKeyAggregator participant S as Sortition - - EVM--)CS: E3Requested + + EVM--)CS: E3Requested CS->>+S: has node? S--)-CS: yes CS--)E3: CiphernodeSelected @@ -35,7 +61,7 @@ sequenceDiagram participant KS as Keyshare participant PTA as PlaintextAggregator participant S as Sortition - + EVM--)E3: CiphertextOutputPublished E3->>PTA: Create new PlaintextAggreator for this e3_id loop @@ -48,4 +74,3 @@ sequenceDiagram PTA--)PTA: Stop KS--)-KS: Stop ``` - diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index b032bdde..96093ad3 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -123,10 +123,16 @@ pub enum EnclaveEvent { Shutdown { id: EventId, data: Shutdown, - }, // CommitteeSelected, - // OutputDecrypted, - // CiphernodeRegistered, - // CiphernodeDeregistered, + }, + /// This is a test event to use in testing + TestEvent { + id: EventId, + data: TestEvent, + }, + // CommitteeSelected, + // OutputDecrypted, + // CiphernodeRegistered, + // CiphernodeDeregistered, } impl EnclaveEvent { @@ -171,6 +177,7 @@ impl From for EventId { EnclaveEvent::EnclaveError { id, .. } => id, EnclaveEvent::E3RequestComplete { id, .. } => id, EnclaveEvent::Shutdown { id, .. } => id, + EnclaveEvent::TestEvent { id, .. } => id, } } } @@ -202,6 +209,7 @@ impl EnclaveEvent { EnclaveEvent::E3RequestComplete { data, .. } => format!("{}", data), EnclaveEvent::EnclaveError { data, .. } => format!("{:?}", data), EnclaveEvent::Shutdown { data, .. } => format!("{:?}", data), + EnclaveEvent::TestEvent { data, .. } => format!("{:?}", data), // _ => "".to_string(), } } @@ -321,6 +329,15 @@ impl From for EnclaveEvent { } } +impl From for EnclaveEvent { + fn from(value: TestEvent) -> Self { + EnclaveEvent::TestEvent { + id: EventId::from(value.clone()), + data: value.clone(), + } + } +} + impl FromError for EnclaveEvent { type Error = anyhow::Error; fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self { @@ -531,6 +548,19 @@ impl Display for Shutdown { } } +#[derive(Message, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[rtype(result = "()")] +pub struct TestEvent { + pub msg: String, +} + +#[cfg(test)] +impl Display for TestEvent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TestEvent(msg: {})", self.msg) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Seed(pub [u8; 32]); impl From for u64 { diff --git a/packages/ciphernode/evm/scripts/build_fixtures.sh b/packages/ciphernode/evm/scripts/build_fixtures.sh new file mode 100755 index 00000000..2b65360e --- /dev/null +++ b/packages/ciphernode/evm/scripts/build_fixtures.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +echo "Building fixtures..." + +echo "{\"abi\": $(solc --abi tests/fixtures/emit_logs.sol | tail -n 1), \"bin\": \"$(solc --bin tests/fixtures/emit_logs.sol| tail -n 1)\"}" | jq '.' > tests/fixtures/emit_logs.json diff --git a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs index b4980398..49193e41 100644 --- a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs +++ b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs @@ -1,4 +1,7 @@ -use crate::{helpers::ReadonlyProvider, EvmEventReader}; +use crate::{ + helpers::{ReadonlyProvider, WithChainId}, + EvmEventReader, +}; use actix::Addr; use alloy::{ primitives::{LogData, B256}, @@ -97,9 +100,9 @@ pub struct CiphernodeRegistrySolReader; impl CiphernodeRegistrySolReader { pub async fn attach( bus: &Addr, - provider: &ReadonlyProvider, + provider: &WithChainId, contract_address: &str, - ) -> Result> { + ) -> Result>> { let addr = EvmEventReader::attach(bus, provider, extractor, contract_address).await?; Ok(addr) } @@ -109,7 +112,7 @@ pub struct CiphernodeRegistrySol; impl CiphernodeRegistrySol { pub async fn attach( bus: &Addr, - provider: &ReadonlyProvider, + provider: &WithChainId, contract_address: &str, ) -> Result<()> { CiphernodeRegistrySolReader::attach(bus, provider, contract_address).await?; diff --git a/packages/ciphernode/evm/src/enclave_sol.rs b/packages/ciphernode/evm/src/enclave_sol.rs index 123bc5ed..bd0c6ef7 100644 --- a/packages/ciphernode/evm/src/enclave_sol.rs +++ b/packages/ciphernode/evm/src/enclave_sol.rs @@ -1,7 +1,7 @@ use crate::{ enclave_sol_reader::EnclaveSolReader, enclave_sol_writer::EnclaveSolWriter, - helpers::{ReadonlyProvider, SignerProvider}, + helpers::{ReadonlyProvider, SignerProvider, WithChainId}, }; use actix::Addr; use anyhow::Result; @@ -11,8 +11,8 @@ pub struct EnclaveSol; impl EnclaveSol { pub async fn attach( bus: &Addr, - read_provider: &ReadonlyProvider, - write_provider: &SignerProvider, + read_provider: &WithChainId, + write_provider: &WithChainId, contract_address: &str, ) -> Result<()> { EnclaveSolReader::attach(bus, read_provider, contract_address).await?; diff --git a/packages/ciphernode/evm/src/enclave_sol_reader.rs b/packages/ciphernode/evm/src/enclave_sol_reader.rs index bef123e5..2dd8477c 100644 --- a/packages/ciphernode/evm/src/enclave_sol_reader.rs +++ b/packages/ciphernode/evm/src/enclave_sol_reader.rs @@ -1,7 +1,8 @@ -use crate::helpers::ReadonlyProvider; +use crate::helpers::{ReadonlyProvider, WithChainId}; use crate::EvmEventReader; use actix::Addr; use alloy::primitives::{LogData, B256}; +use alloy::transports::BoxTransport; use alloy::{sol, sol_types::SolEvent}; use anyhow::Result; use enclave_core::{EnclaveEvent, EventBus}; @@ -83,9 +84,9 @@ pub struct EnclaveSolReader; impl EnclaveSolReader { pub async fn attach( bus: &Addr, - provider: &ReadonlyProvider, + provider: &WithChainId, contract_address: &str, - ) -> Result> { + ) -> Result>> { let addr = EvmEventReader::attach(bus, provider, extractor, contract_address).await?; Ok(addr) } diff --git a/packages/ciphernode/evm/src/enclave_sol_writer.rs b/packages/ciphernode/evm/src/enclave_sol_writer.rs index 474e1134..77d53ab7 100644 --- a/packages/ciphernode/evm/src/enclave_sol_writer.rs +++ b/packages/ciphernode/evm/src/enclave_sol_writer.rs @@ -1,4 +1,5 @@ use crate::helpers::SignerProvider; +use crate::helpers::WithChainId; use actix::prelude::*; use actix::Addr; use alloy::{primitives::Address, sol}; @@ -20,15 +21,15 @@ sol!( /// Consumes events from the event bus and calls EVM methods on the Enclave.sol contract pub struct EnclaveSolWriter { - provider: SignerProvider, + provider: WithChainId, contract_address: Address, bus: Addr, } impl EnclaveSolWriter { - pub async fn new( + pub fn new( bus: &Addr, - provider: &SignerProvider, + provider: &WithChainId, contract_address: Address, ) -> Result { Ok(Self { @@ -40,12 +41,10 @@ impl EnclaveSolWriter { pub async fn attach( bus: &Addr, - provider: &SignerProvider, + provider: &WithChainId, contract_address: &str, ) -> Result> { - let addr = EnclaveSolWriter::new(bus, provider, contract_address.parse()?) - .await? - .start(); + let addr = EnclaveSolWriter::new(bus, provider, contract_address.parse()?)?.start(); bus.send(Subscribe::new("PlaintextAggregated", addr.clone().into())) .await?; @@ -109,7 +108,7 @@ impl Handler for EnclaveSolWriter { } async fn publish_plaintext_output( - provider: SignerProvider, + provider: WithChainId, contract_address: Address, e3_id: E3id, decrypted_output: Vec, diff --git a/packages/ciphernode/evm/src/event_reader.rs b/packages/ciphernode/evm/src/event_reader.rs index cdb11d0e..93264c72 100644 --- a/packages/ciphernode/evm/src/event_reader.rs +++ b/packages/ciphernode/evm/src/event_reader.rs @@ -1,35 +1,47 @@ -use crate::helpers::{self, create_readonly_provider, ensure_ws_rpc, ReadonlyProvider}; +use std::marker::PhantomData; + +use crate::helpers::{self, WithChainId}; use actix::prelude::*; use actix::{Addr, Recipient}; use alloy::primitives::{LogData, B256}; +use alloy::providers::Provider; +use alloy::transports::{BoxTransport, Transport}; use alloy::{eips::BlockNumberOrTag, primitives::Address, rpc::types::Filter}; use anyhow::{anyhow, Result}; use enclave_core::{BusError, EnclaveErrorType, EnclaveEvent, EventBus, Subscribe}; use tokio::sync::oneshot; use tracing::info; -pub type ExtractorFn = fn(&LogData, Option<&B256>, u64) -> Option; +pub type ExtractorFn = fn(&LogData, Option<&B256>, u64) -> Option; /// Connects to Enclave.sol converting EVM events to EnclaveEvents -pub struct EvmEventReader { - provider: Option, +pub struct EvmEventReader +where + P: Provider + Clone + 'static, + T: Transport + Clone + Unpin, +{ + provider: Option>, contract_address: Address, bus: Recipient, - extractor: ExtractorFn, + extractor: ExtractorFn, shutdown_rx: Option>, shutdown_tx: Option>, } -impl EvmEventReader { - pub async fn new( +impl EvmEventReader +where + P: Provider + Clone + 'static, + T: Transport + Clone + Unpin, +{ + pub fn new( bus: &Addr, - provider: &ReadonlyProvider, - extractor: ExtractorFn, - contract_address: Address, + provider: &WithChainId, + extractor: ExtractorFn, + contract_address: &Address, ) -> Result { let (shutdown_tx, shutdown_rx) = oneshot::channel(); Ok(Self { - contract_address, + contract_address: contract_address.clone(), provider: Some(provider.clone()), extractor, bus: bus.clone().into(), @@ -40,13 +52,12 @@ impl EvmEventReader { pub async fn attach( bus: &Addr, - provider: &ReadonlyProvider, - extractor: ExtractorFn, + provider: &WithChainId, + extractor: ExtractorFn, contract_address: &str, ) -> Result> { - let addr = EvmEventReader::new(bus, provider, extractor, contract_address.parse()?) - .await? - .start(); + let addr = + EvmEventReader::new(bus, provider, extractor, &contract_address.parse()?)?.start(); bus.send(Subscribe::new("Shutdown", addr.clone().into())) .await?; @@ -56,7 +67,11 @@ impl EvmEventReader { } } -impl Actor for EvmEventReader { +impl Actor for EvmEventReader +where + P: Provider + Clone + 'static, + T: Transport + Clone + Unpin, +{ type Context = actix::Context; fn started(&mut self, ctx: &mut Self::Context) { let bus = self.bus.clone(); @@ -80,7 +95,11 @@ impl Actor for EvmEventReader { } } -impl Handler for EvmEventReader { +impl Handler for EvmEventReader +where + P: Provider + Clone + 'static, + T: Transport + Clone + Unpin, +{ type Result = (); fn handle(&mut self, msg: EnclaveEvent, _: &mut Self::Context) -> Self::Result { if let EnclaveEvent::Shutdown { .. } = msg { diff --git a/packages/ciphernode/evm/src/helpers.rs b/packages/ciphernode/evm/src/helpers.rs index 36a5d6f1..ecaf7f73 100644 --- a/packages/ciphernode/evm/src/helpers.rs +++ b/packages/ciphernode/evm/src/helpers.rs @@ -3,36 +3,35 @@ use alloy::{ network::{Ethereum, EthereumWallet}, primitives::{LogData, B256}, providers::{ - fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller}, + fillers::{ + BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, + WalletFiller, + }, Identity, Provider, ProviderBuilder, RootProvider, }, rpc::types::Filter, signers::local::PrivateKeySigner, - transports::BoxTransport, + transports::{BoxTransport, Transport}, }; +use anyhow::anyhow; use anyhow::{bail, Context, Result}; use cipher::Cipher; use data::Repository; use enclave_core::{BusError, EnclaveErrorType, EnclaveEvent}; use futures_util::stream::StreamExt; -use std::{env, sync::Arc}; +use std::{env, marker::PhantomData, sync::Arc}; use tokio::{select, sync::oneshot}; use tracing::{info, trace}; use zeroize::Zeroizing; -pub async fn stream_from_evm( - provider: WithChainId

, +pub async fn stream_from_evm, T: Transport + Clone>( + provider: WithChainId, filter: Filter, bus: Recipient, extractor: fn(&LogData, Option<&B256>, u64) -> Option, mut shutdown: oneshot::Receiver<()>, ) { - match provider - .get_provider() - .subscribe_logs(&filter) - .await - .context("Could not subscribe to stream") - { + match provider.get_provider().subscribe_logs(&filter).await { Ok(subscription) => { let mut stream = subscription.into_stream(); loop { @@ -60,7 +59,7 @@ pub async fn stream_from_evm( } } Err(e) => { - bus.err(EnclaveErrorType::Evm, e); + bus.err(EnclaveErrorType::Evm, anyhow!("{}", e)); } }; info!("Exiting stream loop"); @@ -69,23 +68,29 @@ pub async fn stream_from_evm( /// We need to cache the chainId so we can easily use it in a non-async situation /// This wrapper just stores the chain_id with the Provider #[derive(Clone)] -pub struct WithChainId

+// We have to be generic over T as the transport provider in order to handle different transport +// mechanisms such as the HttpClient etc. +pub struct WithChainId where - P: Provider, + P: Provider, + T: Transport + Clone, { provider: Arc

, chain_id: u64, + _t: PhantomData, } -impl

WithChainId

+impl WithChainId where - P: Provider, + P: Provider, + T: Transport + Clone, { pub async fn new(provider: P) -> Result { let chain_id = provider.get_chain_id().await?; Ok(Self { provider: Arc::new(provider), chain_id, + _t: PhantomData, }) } @@ -98,33 +103,36 @@ where } } -pub type ReadonlyProvider = WithChainId>; +pub type ReadonlyProvider = RootProvider; -pub async fn create_readonly_provider(rpc_url: &str) -> Result { +pub async fn create_readonly_provider( + rpc_url: &str, +) -> Result> { let provider = ProviderBuilder::new() .on_builtin(rpc_url) .await .context("Could not create ReadOnlyProvider")? .into(); - Ok(ReadonlyProvider::new(provider).await?) + Ok(WithChainId::new(provider).await?) } -pub type SignerProvider = WithChainId< - FillProvider< +pub type SignerProvider = FillProvider< + JoinFill< JoinFill< - JoinFill, NonceFiller>, ChainIdFiller>, - WalletFiller, + Identity, + JoinFill>>, >, - RootProvider, - BoxTransport, - Ethereum, + WalletFiller, >, + RootProvider, + BoxTransport, + Ethereum, >; pub async fn create_provider_with_signer( rpc_url: &str, signer: &Arc, -) -> Result { +) -> Result> { let wallet = EthereumWallet::from(signer.clone()); let provider = ProviderBuilder::new() .with_recommended_fillers() @@ -132,7 +140,7 @@ pub async fn create_provider_with_signer( .on_builtin(rpc_url) .await?; - Ok(SignerProvider::new(provider).await?) + Ok(WithChainId::new(provider).await?) } pub async fn pull_eth_signer_from_env(var: &str) -> Result> { diff --git a/packages/ciphernode/evm/src/lib.rs b/packages/ciphernode/evm/src/lib.rs index d13e040a..5d01008a 100644 --- a/packages/ciphernode/evm/src/lib.rs +++ b/packages/ciphernode/evm/src/lib.rs @@ -10,5 +10,5 @@ pub use ciphernode_registry_sol::{CiphernodeRegistrySol, CiphernodeRegistrySolRe pub use enclave_sol::EnclaveSol; pub use enclave_sol_reader::EnclaveSolReader; pub use enclave_sol_writer::EnclaveSolWriter; -pub use event_reader::EvmEventReader; +pub use event_reader::{EvmEventReader, ExtractorFn}; pub use registry_filter_sol::{RegistryFilterSol, RegistryFilterSolWriter}; diff --git a/packages/ciphernode/evm/src/registry_filter_sol.rs b/packages/ciphernode/evm/src/registry_filter_sol.rs index c62ce44c..2c8dedf9 100644 --- a/packages/ciphernode/evm/src/registry_filter_sol.rs +++ b/packages/ciphernode/evm/src/registry_filter_sol.rs @@ -1,9 +1,10 @@ -use crate::helpers::SignerProvider; +use crate::helpers::{SignerProvider, WithChainId}; use actix::prelude::*; use alloy::{ primitives::{Address, Bytes, U256}, rpc::types::TransactionReceipt, sol, + transports::BoxTransport, }; use anyhow::Result; use enclave_core::{ @@ -19,7 +20,7 @@ sol!( ); pub struct RegistryFilterSolWriter { - provider: SignerProvider, + provider: WithChainId, contract_address: Address, bus: Addr, } @@ -27,7 +28,7 @@ pub struct RegistryFilterSolWriter { impl RegistryFilterSolWriter { pub async fn new( bus: &Addr, - provider: &SignerProvider, + provider: &WithChainId, contract_address: Address, ) -> Result { Ok(Self { @@ -39,7 +40,7 @@ impl RegistryFilterSolWriter { pub async fn attach( bus: &Addr, - provider: &SignerProvider, + provider: &WithChainId, contract_address: &str, ) -> Result> { let addr = RegistryFilterSolWriter::new(bus, provider, contract_address.parse()?) @@ -106,7 +107,7 @@ impl Handler for RegistryFilterSolWriter { } pub async fn publish_committee( - provider: SignerProvider, + provider: WithChainId, contract_address: Address, e3_id: E3id, nodes: OrderedSet, @@ -128,7 +129,7 @@ pub struct RegistryFilterSol; impl RegistryFilterSol { pub async fn attach( bus: &Addr, - provider: &SignerProvider, + provider: &WithChainId, contract_address: &str, ) -> Result<()> { RegistryFilterSolWriter::attach(bus, provider, contract_address).await?; diff --git a/packages/ciphernode/evm/tests/evm_reader.rs b/packages/ciphernode/evm/tests/evm_reader.rs new file mode 100644 index 00000000..96315c25 --- /dev/null +++ b/packages/ciphernode/evm/tests/evm_reader.rs @@ -0,0 +1,80 @@ +use actix::Actor; +use alloy::{ + node_bindings::Anvil, + providers::{ProviderBuilder, WsConnect}, + sol, + sol_types::SolEvent, +}; +use anyhow::Result; +use enclave_core::{EnclaveEvent, EventBus, GetHistory, TestEvent}; +use evm::{helpers::WithChainId, EvmEventReader}; +use std::{sync::Arc, time::Duration}; +use tokio::time::sleep; + +sol!( + #[sol(rpc)] + EmitLogs, + "tests/fixtures/emit_logs.json" +); + +#[actix::test] +async fn test_logs() -> Result<()> { + // Create a WS provider + // NOTE: Anvil must be available on $PATH + let anvil = Anvil::new().block_time(1).try_spawn()?; + let ws = WsConnect::new(anvil.ws_endpoint()); + let provider = ProviderBuilder::new().on_ws(ws).await?; + let arc_provider = WithChainId::new(provider).await?; + let contract = Arc::new(EmitLogs::deploy(arc_provider.get_provider()).await?); + let bus = EventBus::new(true).start(); + + EvmEventReader::attach( + &bus, + &arc_provider, + |data, topic, _| match topic { + Some(&EmitLogs::ValueChanged::SIGNATURE_HASH) => { + let Ok(event) = EmitLogs::ValueChanged::decode_log_data(data, true) else { + return None; + }; + Some(EnclaveEvent::from(TestEvent { + msg: event.newValue, + })) + } + _ => None, + }, + &contract.address().to_string(), + ) + .await?; + + contract + .setValue("hello".to_string()) + .send() + .await? + .watch() + .await?; + + contract + .setValue("world!".to_string()) + .send() + .await? + .watch() + .await?; + + sleep(Duration::from_millis(1)).await; + + let history = bus.send(GetHistory).await?; + + assert_eq!(history.len(), 2); + + let msgs: Vec<_> = history + .into_iter() + .filter_map(|evt| match evt { + EnclaveEvent::TestEvent { data, .. } => Some(data.msg), + _ => None, + }) + .collect(); + + assert_eq!(msgs, vec!["hello", "world!"]); + + Ok(()) +} diff --git a/packages/ciphernode/evm/tests/fixtures/.gitignore b/packages/ciphernode/evm/tests/fixtures/.gitignore new file mode 100644 index 00000000..8dd919b5 --- /dev/null +++ b/packages/ciphernode/evm/tests/fixtures/.gitignore @@ -0,0 +1,2 @@ +# ignore .json +*.json diff --git a/packages/ciphernode/evm/tests/fixtures/emit_logs.sol b/packages/ciphernode/evm/tests/fixtures/emit_logs.sol new file mode 100644 index 00000000..e9bad33c --- /dev/null +++ b/packages/ciphernode/evm/tests/fixtures/emit_logs.sol @@ -0,0 +1,21 @@ +pragma solidity >=0.4.24; + +contract EmitLogs { + + event ValueChanged(address indexed author, string oldValue, string newValue); + + string _value; + + constructor() { + _value = ""; + } + + function getValue() view public returns (string memory) { + return _value; + } + + function setValue(string memory value) public { + emit ValueChanged(msg.sender, _value, value); + _value = value; + } +} diff --git a/packages/ciphernode/scripts/test.sh b/packages/ciphernode/scripts/test.sh new file mode 100755 index 00000000..79de102f --- /dev/null +++ b/packages/ciphernode/scripts/test.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +pushd ./evm && ./scripts/build_fixtures.sh && popd + +cargo test -- $@