From 2fb787875ebdc375522008d38d718eec8e613a1c Mon Sep 17 00:00:00 2001 From: "Ian K. Guimaraes" Date: Wed, 13 Nov 2024 18:35:55 -0300 Subject: [PATCH 1/2] feat: add support to EIP-7702 transactions --- Cargo.lock | 355 +++++++++++++----- crates/core/Cargo.toml | 3 +- crates/core/src/common/block.rs | 43 +-- crates/core/src/common/query_result.rs | 184 ++++++++- crates/core/src/common/transaction.rs | 73 ++-- .../interpreter/backend/execution_engine.rs | 22 +- .../src/interpreter/backend/resolve_block.rs | 40 +- .../backend/resolve_transaction.rs | 182 +++------ .../core/src/interpreter/frontend/parser.rs | 13 +- .../src/interpreter/frontend/productions.pest | 22 +- docs/query.md | 4 +- examples/get-transaction.eql | 2 +- 12 files changed, 597 insertions(+), 346 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3163cac..c9e5e2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,9 +69,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy" -version = "0.2.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45855eb65e9cc70294ebea1279f6d8ee0636bf2ed3897683ebbae2739975ae8c" +checksum = "b5b524b8c28a7145d1fe4950f84360b5de3e307601679ff0558ddc20ea229399" dependencies = [ "alloy-consensus", "alloy-contract", @@ -99,27 +99,30 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58047cc851e58c26224521d1ecda466e3d746ebca0274cd5427aa660a88c353" +checksum = "ef11c6b2dfbf77dca7bafc6759860391395f07c04d5486f2a2e2563d2961639b" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", + "auto_impl", "c-kzg", + "derive_more", "serde", ] [[package]] name = "alloy-contract" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5d42d9f87896536234b0fac1a84ad9d9dc7a4b27839cac35d0899e64ddf083" +checksum = "8faa407ef916bfe0677c52c9b2258ce0698c53e9e15a837d1501e3ae9e57421a" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-network", + "alloy-network-primitives", "alloy-primitives", "alloy-provider", "alloy-rpc-types-eth", @@ -132,21 +135,22 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529fc6310dc1126c8de51c376cbc59c79c7f662bd742be7dc67055d5421a81b4" +checksum = "47ef9e96462d0b9fee9008c53c1f3d017b9498fcdef3ad8d728db98afef47955" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-primitives", + "alloy-rlp", "alloy-sol-types", ] [[package]] name = "alloy-dyn-abi" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" +checksum = "85132f2698b520fab3f54beed55a44389f7006a7b557a0261e1e69439dcc1572" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -159,16 +163,42 @@ dependencies = [ "winnow 0.6.16", ] +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "serde", +] + [[package]] name = "alloy-eips" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a3e14fa0d152d00bd8daf605eb74ad397efb0f54bd7155585823dddb4401e" +checksum = "33d6c0c1744a7af7d325dca6b5c5bb431a6307c0961088f7a236ca2694c4a87e" dependencies = [ + "alloy-eip2930", + "alloy-eip7702", "alloy-primitives", "alloy-rlp", "alloy-serde", "c-kzg", + "derive_more", "once_cell", "serde", "sha2", @@ -176,9 +206,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cb76c8a3913f2466c5488f3a915e3a15d15596bdc935558c1a9be75e9ec508" +checksum = "95a5a0a01ef6ec3cd3ebd52a7b3bc7f8a92b23e478e69c07abd94abf05e6b48e" dependencies = [ "alloy-primitives", "alloy-serde", @@ -187,9 +217,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" +checksum = "ded610181f3dad5810f6ff12d1a99994cf9b42d2fcb7709029352398a5da5ae6" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -199,11 +229,12 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a9feec2352c78545d1a37415699817bae8dc41654bd1bfe57d6cdd5433bd" +checksum = "65fd0e2cff5ab68defc5050ff9e81cb053c5b52cf4809fc8786664898e29ae75" dependencies = [ "alloy-primitives", + "alloy-sol-types", "serde", "serde_json", "thiserror", @@ -212,13 +243,14 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3223d71dc78f464b2743418d0be8b5c894313e272105a6206ad5e867d67b3ce2" +checksum = "96c9eca0c04ca8a663966ce7f5b19c03927f2b4d82910cb76cb4008490cfa838" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", + "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", @@ -227,42 +259,64 @@ dependencies = [ "async-trait", "auto_impl", "futures-utils-wasm", + "serde", + "serde_json", "thiserror", ] +[[package]] +name = "alloy-network-primitives" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c3050f19dc93a7f09fef670c8db04a15e7e2901494ca40decbce323be69643" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-primitives" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +checksum = "fd58d377699e6cfeab52c4a9d28bdc4ef37e2bd235ff2db525071fe37a2e9af5" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more", + "foldhash", + "hashbrown 0.15.1", "hex-literal", + "indexmap 2.6.0", "itoa", "k256", "keccak-asm", + "paste", "proptest", "rand", "ruint", + "rustc-hash", "serde", + "sha3", "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29da7457d853cb8199ec04b227d5d2ef598be3e59fc2bbad70c8be213292f32" +checksum = "df8e5a28e7c4c04afc0f20b2aecf6f9214d6cfd5009187c0b8616a8f8918739c" dependencies = [ "alloy-chains", "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network", + "alloy-network-primitives", "alloy-primitives", "alloy-rpc-client", "alloy-rpc-types-eth", @@ -275,20 +329,24 @@ dependencies = [ "futures", "futures-utils-wasm", "lru", + "parking_lot", "pin-project", "reqwest", + "schnellru", "serde", "serde_json", + "thiserror", "tokio", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-rlp" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" +checksum = "da0822426598f95e45dd1ea32a738dac057529a709ee645fcc516ffa4cbde08f" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -297,9 +355,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" +checksum = "2b09cae092c27b6f1bde952653a22708691802e57bfef4a2973b80bea21efd3f" dependencies = [ "proc-macro2", "quote", @@ -308,11 +366,12 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9e609524fa31c2c70eb24c0da60796809193ad4787a6dfe6d0db0d3ac112d" +checksum = "0336362936bb9fef88f27d51f2ede8c15cdfdb7f81b042e74257770052547101" dependencies = [ "alloy-json-rpc", + "alloy-primitives", "alloy-transport", "alloy-transport-http", "futures", @@ -322,17 +381,19 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower", + "tower 0.5.1", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-rpc-types" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5d76f1e8b22f48b7b8f985782b68e7eb3938780e50e8b646a53e41a598cdf5" +checksum = "ac9a46bc01bc27dbf4dd27d46986eda661ffe99e78aea3078a77b8c064072b01" dependencies = [ + "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "serde", @@ -340,27 +401,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605fa8462732bb8fd0645a9941e12961e079d45ae6a44634c826f8229c187bdf" +checksum = "d58fa055e02d04bc70443ecce984951fb5be02d2c843c640ca48237cdec66af1" dependencies = [ "alloy-consensus", "alloy-eips", + "alloy-network-primitives", "alloy-primitives", "alloy-rlp", "alloy-serde", "alloy-sol-types", + "derive_more", "itertools 0.13.0", "serde", "serde_json", - "thiserror", ] [[package]] name = "alloy-serde" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c5b9057acc02aee1b8aac2b5a0729cb0f73d080082c111313e5d1f92a96630" +checksum = "feafd71e0e252b063fe4b07962beedf0445e66b07b4b44af178863d21e75b0fa" dependencies = [ "alloy-primitives", "serde", @@ -369,9 +431,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37f10592696f4ab8b687d5a8ab55e998a14ea0ca5f8eb20ad74a96ad671bb54a" +checksum = "ebad84d52550351438ec7f151dbc551f870c31eecf23b473df5b779a91eee8ca" dependencies = [ "alloy-primitives", "async-trait", @@ -383,13 +445,13 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +checksum = "8a1b42ac8f45e2f49f4bcdd72cbfde0bb148f5481d403774ffa546e48b83efc1" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.66", @@ -397,16 +459,16 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +checksum = "06318f1778e57f36333e850aa71bd1bb5e560c10279e236622faae0470c50412" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.2.6", - "proc-macro-error", + "indexmap 2.6.0", + "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.66", @@ -416,9 +478,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" +checksum = "eaebb9b0ad61a41345a22c9279975c0cdd231b97947b10d7aad1cf0a7181e4a5" dependencies = [ "alloy-json-abi", "const-hex", @@ -433,9 +495,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" +checksum = "12c71028bfbfec210e24106a542aad3def7caf1a70e2c05710e92a98481980d3" dependencies = [ "serde", "winnow 0.6.16", @@ -443,9 +505,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +checksum = "374d7fb042d68ddfe79ccb23359de3007f6d4d53c13f703b64fb0db422132111" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -456,9 +518,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b44b0f6f4a2593b258fa7b6cae8968e6a4c404d9ef4f5bc74401f2d04fa23fa" +checksum = "da63700a2b3176b3009a6d3672d0c657280a517dcec7659c991c55e863a83165" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -468,22 +530,23 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "tower", + "tower 0.5.1", "tracing", "url", + "wasmtimer", ] [[package]] name = "alloy-transport-http" -version = "0.2.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8f1eefa8cb9e7550740ee330feba4fed303a77ad3085707546f9152a88c380" +checksum = "6613c3abc567b710217d241650ef73cfb8df9bcdc2ef23fdedabf363637e2a00" dependencies = [ "alloy-json-rpc", "alloy-transport", "reqwest", "serde_json", - "tower", + "tower 0.5.1", "tracing", "url", ] @@ -1270,12 +1333,6 @@ dependencies = [ "tiny-keccak", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "core-foundation" version = "0.9.4" @@ -1493,11 +1550,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", + "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", @@ -1536,15 +1594,23 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.18" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.0", "syn 2.0.66", + "unicode-xid", ] [[package]] @@ -1634,9 +1700,10 @@ dependencies = [ [[package]] name = "eql_core" -version = "0.1.18" +version = "0.1.19" dependencies = [ "alloy", + "alloy-eip7702", "anyhow", "arrow", "criterion", @@ -1783,6 +1850,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" @@ -1988,6 +2061,16 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +dependencies = [ + "foldhash", + "serde", +] + [[package]] name = "heck" version = "0.4.1" @@ -2126,7 +2209,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", + "tower 0.4.13", "tower-service", "tracing", ] @@ -2202,12 +2285,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", + "serde", ] [[package]] @@ -2217,7 +2301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", - "indexmap 2.2.6", + "indexmap 2.6.0", "is-terminal", "itoa", "log", @@ -2312,6 +2396,15 @@ dependencies = [ "sha2", ] +[[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.1" @@ -3027,6 +3120,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "proc-macro2" version = "1.0.85" @@ -3095,6 +3210,7 @@ dependencies = [ "libc", "rand_chacha", "rand_core", + "serde", ] [[package]] @@ -3217,7 +3333,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tokio-native-tls", "tower-service", @@ -3293,6 +3409,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -3388,6 +3510,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" @@ -3548,6 +3681,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.1" @@ -3750,9 +3893,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" +checksum = "edf42e81491fb8871b74df3d222c64ae8cbc1269ea509fa768a3ed3e1b0ac8cb" dependencies = [ "paste", "proc-macro2", @@ -3760,6 +3903,12 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.1" @@ -3960,7 +4109,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.6.0", "toml_datetime", "winnow 0.5.40", ] @@ -3978,20 +4127,33 @@ dependencies = [ "tokio", "tower-layer", "tower-service", - "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", ] [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3999,7 +4161,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4098,6 +4259,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "url" version = "2.5.2" @@ -4239,6 +4406,20 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasmtimer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4f099acbc1043cc752b91615b24b02d7f6fcd975bd781fed9f50b3c3e15bf7" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "web-sys" version = "0.3.69" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 9d2f354..356ff24 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -10,7 +10,8 @@ repository = "https://github.com/iankressin/eql" readme = "README.md" [dependencies] -alloy = { version = "0.2", features = ["std", "contract", "provider-http", "network", "rpc-types"] } +alloy = { version = "0.6.4", features = ["std", "contract", "provider-http", "network", "rpc-types"] } +alloy-eip7702 = "0.4.1" pest = "2.7.10" pest_derive = "2.6" tokio = { version = "1", features = ["macros", "rt"] } diff --git a/crates/core/src/common/block.rs b/crates/core/src/common/block.rs index 307d373..948118d 100644 --- a/crates/core/src/common/block.rs +++ b/crates/core/src/common/block.rs @@ -3,6 +3,7 @@ use crate::interpreter::frontend::parser::Rule; use alloy::{ eips::BlockNumberOrTag, providers::{Provider, RootProvider}, + rpc::types::BlockTransactionsKind, transports::http::{Client, Http}, }; use anyhow::Result; @@ -303,15 +304,10 @@ impl BlockRange { provider: &Arc>>, ) -> Result> { let (start_block, end_block) = self.range(); - let start_block_number = self - .get_block_number_from_tag(provider.clone(), start_block) - .await?; + let start_block_number = get_block_number_from_tag(provider.clone(), &start_block).await?; let end_block_number = match end_block { - Some(end) => Some( - self.get_block_number_from_tag(provider.clone(), end) - .await?, - ), + Some(end) => Some(get_block_number_from_tag(provider.clone(), &end).await?), None => None, }; @@ -329,23 +325,6 @@ impl BlockRange { None => Ok(vec![start_block_number]), } } - - async fn get_block_number_from_tag( - &self, - provider: Arc>>, - number_or_tag: BlockNumberOrTag, - ) -> Result { - match number_or_tag { - BlockNumberOrTag::Number(number) => Ok(number), - block_tag => match provider.get_block_by_number(block_tag, false).await? { - Some(block) => match block.header.number { - Some(number) => Ok(number), - None => Err(BlockRangeError::UnableToFetchBlockNumber(number_or_tag).into()), - }, - None => Err(BlockRangeError::UnableToFetchBlockNumber(number_or_tag).into()), - }, - } - } } impl Display for BlockRange { @@ -366,3 +345,19 @@ impl Display for BlockRange { } } } + +pub async fn get_block_number_from_tag( + provider: Arc>>, + number_or_tag: &BlockNumberOrTag, +) -> Result { + match number_or_tag { + BlockNumberOrTag::Number(number) => Ok(*number), + block_tag => match provider + .get_block_by_number(*block_tag, BlockTransactionsKind::Hashes) + .await? + { + Some(block) => Ok(block.header.number), + None => Err(BlockRangeError::UnableToFetchBlockNumber(number_or_tag.clone()).into()), + }, + } +} diff --git a/crates/core/src/common/query_result.rs b/crates/core/src/common/query_result.rs index 490a26c..73d6f06 100644 --- a/crates/core/src/common/query_result.rs +++ b/crates/core/src/common/query_result.rs @@ -1,5 +1,7 @@ use crate::common::chain::Chain; use alloy::primitives::{Address, Bloom, Bytes, FixedBytes, B256, U256}; +use alloy_eip7702::SignedAuthorization; +use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize, Serializer}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] @@ -43,10 +45,10 @@ pub struct BlockQueryRes { pub extra_data: Option, pub mix_hash: Option, pub total_difficulty: Option, - pub base_fee_per_gas: Option, + pub base_fee_per_gas: Option, pub withdrawals_root: Option, - pub blob_gas_used: Option, - pub excess_blob_gas: Option, + pub blob_gas_used: Option, + pub excess_blob_gas: Option, pub parent_beacon_block_root: Option, } @@ -99,10 +101,10 @@ impl Default for AccountQueryRes { } #[serde_with::skip_serializing_none] -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] +#[derive(Debug, PartialEq, Eq, Deserialize, Clone)] pub struct TransactionQueryRes { pub chain: Option, - pub transaction_type: Option, + pub r#type: Option, pub hash: Option>, pub from: Option
, pub to: Option
, @@ -110,40 +112,184 @@ pub struct TransactionQueryRes { #[serde(serialize_with = "serialize_option_u256")] pub value: Option, pub gas_price: Option, - pub gas: Option, + pub gas_limit: Option, + pub effective_gas_price: Option, pub status: Option, pub chain_id: Option, - pub v: Option, + pub v: Option, pub r: Option, pub s: Option, pub max_fee_per_blob_gas: Option, pub max_fee_per_gas: Option, pub max_priority_fee_per_gas: Option, pub y_parity: Option, + pub authorization_list: Option>, } impl Default for TransactionQueryRes { fn default() -> Self { Self { chain: None, - transaction_type: None, + r#type: None, hash: None, from: None, to: None, data: None, value: None, gas_price: None, - gas: None, + gas_limit: None, status: None, chain_id: None, v: None, r: None, s: None, + effective_gas_price: None, max_fee_per_blob_gas: None, max_fee_per_gas: None, max_priority_fee_per_gas: None, y_parity: None, + authorization_list: None, + } + } +} + +impl TransactionQueryRes { + pub fn has_value(&self) -> bool { + self.chain.is_some() + || self.r#type.is_some() + || self.hash.is_some() + || self.from.is_some() + || self.to.is_some() + || self.data.is_some() + || self.value.is_some() + || self.gas_price.is_some() + || self.gas_limit.is_some() + || self.effective_gas_price.is_some() + || self.status.is_some() + || self.chain_id.is_some() + || self.v.is_some() + || self.r.is_some() + || self.s.is_some() + || self.max_fee_per_blob_gas.is_some() + || self.max_fee_per_gas.is_some() + || self.max_priority_fee_per_gas.is_some() + || self.y_parity.is_some() + || self.authorization_list.is_some() + } + + fn get_field_values(&self) -> Vec<(&'static str, String)> { + let mut fields = Vec::new(); + if let Some(chain) = &self.chain { + fields.push(("chain", Some(chain.to_string()))); + } + if let Some(r#type) = self.r#type { + fields.push(("type", Some(r#type.to_string()))); + } + if let Some(hash) = &self.hash { + fields.push(("hash", Some(format!("{hash:?}")))); + } + if let Some(from) = &self.from { + fields.push(("from", Some(from.to_string()))); + } + if let Some(to) = &self.to { + fields.push(("to", Some(to.to_string()))); + } + if let Some(data) = &self.data { + fields.push(("data", Some(format!("{data:?}")))); + } + if let Some(value) = &self.value { + fields.push(("value", Some(value.to_string()))); + } + if let Some(gas_price) = self.gas_price { + fields.push(("gas_price", Some(gas_price.to_string()))); + } + if let Some(gas_limit) = self.gas_limit { + fields.push(("gas_limit", Some(gas_limit.to_string()))); + } + if let Some(effective_gas_price) = self.effective_gas_price { + fields.push(("effective_gas_price", Some(effective_gas_price.to_string()))); + } + if let Some(status) = self.status { + fields.push(("status", Some(status.to_string()))); + } + if let Some(chain_id) = self.chain_id { + fields.push(("chain_id", Some(chain_id.to_string()))); + } + if let Some(v) = self.v { + fields.push(("v", Some(v.to_string()))); + } + if let Some(r) = &self.r { + fields.push(("r", Some(r.to_string()))); + } + if let Some(s) = &self.s { + fields.push(("s", Some(s.to_string()))); + } + if let Some(max_fee_per_blob_gas) = self.max_fee_per_blob_gas { + fields.push(( + "max_fee_per_blob_gas", + Some(max_fee_per_blob_gas.to_string()), + )); + } + if let Some(max_fee_per_gas) = self.max_fee_per_gas { + fields.push(("max_fee_per_gas", Some(max_fee_per_gas.to_string()))); + } + if let Some(max_priority_fee_per_gas) = self.max_priority_fee_per_gas { + fields.push(( + "max_priority_fee_per_gas", + Some(max_priority_fee_per_gas.to_string()), + )); + } + if let Some(y_parity) = self.y_parity { + fields.push(("y_parity", Some(y_parity.to_string()))); + } + + if let Some(auths) = &self.authorization_list { + for (i, auth) in auths.iter().enumerate() { + fields.push(( + Box::leak(format!("authorization_list_{i}_chain_id").into_boxed_str()), + Some(auth.chain_id.to_string()), + )); + fields.push(( + Box::leak(format!("authorization_list_{i}_address").into_boxed_str()), + Some(auth.address.to_string()), + )); + fields.push(( + Box::leak(format!("authorization_list_{i}_r").into_boxed_str()), + Some(format!("{:?}", auth.r())), + )); + fields.push(( + Box::leak(format!("authorization_list_{i}_s").into_boxed_str()), + Some(format!("{:?}", auth.s())), + )); + fields.push(( + Box::leak(format!("authorization_list_{i}_y_parity").into_boxed_str()), + Some(format!("{:?}", auth.y_parity())), + )); + fields.push(( + Box::leak(format!("authorization_list_{i}_nonce").into_boxed_str()), + Some(auth.nonce.to_string()), + )); + } } + + fields + .into_iter() + .map(|(name, value)| (name, value.unwrap_or_default())) + .collect() + } +} + +impl Serialize for TransactionQueryRes { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let fields = self.get_field_values(); + let mut state = serializer.serialize_struct("TransactionQueryRes", fields.len())?; + for (field_name, value) in fields { + state.serialize_field(field_name, &value)?; + } + state.end() } } @@ -187,6 +333,16 @@ impl Default for LogQueryRes { } } +fn serialize_option_u256(option: &Option, serializer: S) -> Result +where + S: Serializer, +{ + match option { + Some(u256) => serializer.serialize_some(&u256.to_string()), + None => serializer.serialize_none(), + } +} + #[cfg(test)] mod test { use std::str::FromStr; @@ -210,13 +366,3 @@ mod test { assert_eq!("{\"value\":\"100\"}", u256_str); } } - -fn serialize_option_u256(option: &Option, serializer: S) -> Result -where - S: Serializer, -{ - match option { - Some(u256) => serializer.serialize_some(&u256.to_string()), - None => serializer.serialize_none(), - } -} diff --git a/crates/core/src/common/transaction.rs b/crates/core/src/common/transaction.rs index a4c54a4..69e36e7 100644 --- a/crates/core/src/common/transaction.rs +++ b/crates/core/src/common/transaction.rs @@ -63,14 +63,17 @@ impl Transaction { pub fn filter(&self, tx: &TransactionQueryRes) -> bool { if let Some(filters) = &self.filters { filters.iter().all(|filter| match filter { - TransactionFilter::TransactionType(t) => t.compare(&tx.transaction_type.unwrap()), + TransactionFilter::Type(t) => t.compare(&tx.r#type.unwrap()), TransactionFilter::Hash(h) => h.compare(&tx.hash.unwrap()), TransactionFilter::From(f) => f.compare(&tx.from.unwrap()), TransactionFilter::To(t) => t.compare(&tx.to.unwrap()), TransactionFilter::Data(d) => d.compare(&tx.data.clone().unwrap()), TransactionFilter::Value(v) => v.compare(&tx.value.unwrap()), TransactionFilter::GasPrice(gp) => gp.compare(&tx.gas_price.unwrap()), - TransactionFilter::Gas(g) => g.compare(&tx.gas.unwrap()), + TransactionFilter::GasLimit(g) => g.compare(&tx.gas_limit.unwrap()), + TransactionFilter::EffectiveGasPrice(egp) => { + egp.compare(&tx.effective_gas_price.unwrap()) + } TransactionFilter::ChainId(cid) => cid.compare(&tx.chain_id.unwrap()), TransactionFilter::Status(s) => s.compare(&tx.status.unwrap()), TransactionFilter::V(v) => v.compare(&tx.v.unwrap()), @@ -172,14 +175,15 @@ impl TryFrom> for Transaction { #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, EnumVariants)] pub enum TransactionField { - TransactionType, + Type, Hash, From, To, Data, Value, GasPrice, - Gas, + GasLimit, + EffectiveGasPrice, Status, ChainId, V, @@ -190,19 +194,21 @@ pub enum TransactionField { MaxPriorityFeePerGas, YParity, Chain, + AuthorizationList, } impl std::fmt::Display for TransactionField { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - TransactionField::TransactionType => write!(f, "transaction_type"), + TransactionField::Type => write!(f, "type"), TransactionField::Hash => write!(f, "hash"), TransactionField::From => write!(f, "from"), TransactionField::To => write!(f, "to"), TransactionField::Data => write!(f, "data"), TransactionField::Value => write!(f, "value"), TransactionField::GasPrice => write!(f, "gas_price"), - TransactionField::Gas => write!(f, "gas"), + TransactionField::GasLimit => write!(f, "gas_limit"), + TransactionField::EffectiveGasPrice => write!(f, "effective_gas_price"), TransactionField::Status => write!(f, "status"), TransactionField::ChainId => write!(f, "chain_id"), TransactionField::V => write!(f, "v"), @@ -213,6 +219,7 @@ impl std::fmt::Display for TransactionField { TransactionField::MaxPriorityFeePerGas => write!(f, "max_priority_fee_per_gas"), TransactionField::YParity => write!(f, "y_parity"), TransactionField::Chain => write!(f, "chain"), + TransactionField::AuthorizationList => write!(f, "authorization_list"), } } } @@ -229,14 +236,15 @@ impl TryFrom<&str> for TransactionField { fn try_from(value: &str) -> Result { match value { - "transaction_type" => Ok(TransactionField::TransactionType), + "type" => Ok(TransactionField::Type), "hash" => Ok(TransactionField::Hash), "from" => Ok(TransactionField::From), "to" => Ok(TransactionField::To), "data" => Ok(TransactionField::Data), "value" => Ok(TransactionField::Value), "gas_price" => Ok(TransactionField::GasPrice), - "gas" => Ok(TransactionField::Gas), + "gas_limit" => Ok(TransactionField::GasLimit), + "effective_gas_price" => Ok(TransactionField::EffectiveGasPrice), "status" => Ok(TransactionField::Status), "chain_id" => Ok(TransactionField::ChainId), "v" => Ok(TransactionField::V), @@ -247,6 +255,7 @@ impl TryFrom<&str> for TransactionField { "max_priority_fee_per_gas" => Ok(TransactionField::MaxPriorityFeePerGas), "y_parity" => Ok(TransactionField::YParity), "chain" => Ok(TransactionField::Chain), + "authorization_list" => Ok(TransactionField::AuthorizationList), invalid_field => Err(TransactionFieldError::InvalidTransactionField( invalid_field.to_string(), )), @@ -274,18 +283,19 @@ pub enum TransactionFilterError { #[derive(Debug, PartialEq)] pub enum TransactionFilter { - TransactionType(EqualityFilter), + Type(EqualityFilter), Hash(EqualityFilter), From(EqualityFilter
), To(EqualityFilter
), Data(EqualityFilter), Value(FilterType), GasPrice(FilterType), - Gas(FilterType), + GasLimit(FilterType), + EffectiveGasPrice(FilterType), ChainId(EqualityFilter), BlockId(BlockId), Status(EqualityFilter), - V(EqualityFilter), + V(EqualityFilter), R(EqualityFilter), S(EqualityFilter), MaxFeePerBlobGas(FilterType), @@ -325,7 +335,7 @@ impl TransactionFilter { } } - // Helper function to parse equality filter components + /// Helper function to parse equality filter components fn parse_equality_filter<'a, T, F>( pair: Pair<'a, Rule>, value_parser: F, @@ -340,7 +350,7 @@ impl TransactionFilter { match operator { Some(op) => { - let value = value_parser(inner_pair.as_str()); + let value = value_parser(inner_pair.as_str().trim()); let filter = EqualityFilter::try_from((op, value)).map_err(|e| FilterError::from(e))?; Ok(constructor(filter)) @@ -372,6 +382,11 @@ impl TransactionFilter { start, end, )))) } + Rule::type_filter_type => Self::parse_equality_filter( + pair, + |s| s.parse::().unwrap(), + TransactionFilter::Type, + ), Rule::value_filter_type => Self::parse_filter( pair, |s| U256::from_str(s).unwrap(), @@ -382,9 +397,11 @@ impl TransactionFilter { |s| s.parse::().unwrap(), TransactionFilter::GasPrice, ), - Rule::gas_filter_type => { - Self::parse_filter(pair, |s| s.parse::().unwrap(), TransactionFilter::Gas) - } + Rule::gas_limit_filter_type => Self::parse_filter( + pair, + |s| s.parse::().unwrap(), + TransactionFilter::GasLimit, + ), Rule::max_fee_per_blob_gas_filter_type => Self::parse_filter( pair, |s| s.parse::().unwrap(), @@ -436,17 +453,17 @@ impl TransactionFilter { EqualityFilter::try_from((operator, value == "true")).unwrap(), )) } - _ => { - return Err(TransactionFilterError::InvalidTransactionFilterProperty( - pair.as_str().to_string(), - )); - } + _ => Err(TransactionFilterError::InvalidTransactionFilterProperty( + pair.as_str().to_string(), + )), } } } #[cfg(test)] mod tests { + use alloy::eips::BlockNumberOrTag; + use super::*; use crate::common::filters::ComparisonFilter; @@ -474,15 +491,23 @@ mod tests { fn test_return_false_if_tx_does_not_pass_any_filters() { let tx_query_res = TransactionQueryRes { value: Some(U256::from(1)), + r#type: Some(2), ..Default::default() }; - let filter = FilterType::Comparison(ComparisonFilter::Gte(U256::from(1000000000))); + // let filter = FilterType::Comparison(ComparisonFilter::Gte(U256::from(1000000000))); + // GET type FROM tx WHERE block = 45087:45187, type = 4 ON mekong let transaction = Transaction::new( None, - Some(vec![TransactionFilter::Value(filter)]), - TransactionField::all_variants().to_vec(), + Some(vec![ + TransactionFilter::BlockId(BlockId::Range(BlockRange::new( + BlockNumberOrTag::Number(45087), + Some(BlockNumberOrTag::Number(45187)), + ))), + TransactionFilter::Type(EqualityFilter::Eq(4)), + ]), + vec![TransactionField::Type], ); assert_eq!(false, transaction.filter(&tx_query_res)); diff --git a/crates/core/src/interpreter/backend/execution_engine.rs b/crates/core/src/interpreter/backend/execution_engine.rs index eb97f2b..b699e9f 100644 --- a/crates/core/src/interpreter/backend/execution_engine.rs +++ b/crates/core/src/interpreter/backend/execution_engine.rs @@ -54,7 +54,7 @@ impl ExecutionEngine { }; if let Some(dump) = &expr.dump { - dump_results(&result, dump); + let _ = dump_results(&result, dump); } Ok(result) @@ -238,7 +238,7 @@ mod test { })]; let expected = vec![ExpressionResult::Transaction(vec![ TransactionQueryRes { - transaction_type: Some(2), + r#type: Some(2), hash: Some(b256!( "72546b3ca8ef0dfb85fe66d19645e44cb519858c72fbcad0e1c1699256fed890" )), @@ -246,11 +246,12 @@ mod test { to: Some(address!("2eeb301387d6bda23e02fa0c7463507c68b597b5")), data: Some(bytes!("")), value: Some(U256::from(234808500010631948_u128)), - gas_price: Some(10209184711_u128), - gas: Some(21000), + gas_price: None, + gas_limit: Some(21000), + effective_gas_price: Some(10209184711_u128), status: Some(true), chain_id: Some(1), - v: Some(U256::from(0)), + v: Some(false), r: Some(U256::from_str("105656622829170817033829205634607968479218860016837137132236076370603621041980").unwrap()), s: Some(U256::from_str("15038977765364444198936700207894720753481416564436657360670639019817488048130").unwrap()), max_fee_per_blob_gas: None, @@ -258,9 +259,10 @@ mod test { max_priority_fee_per_gas: Some(0), y_parity: Some(false), chain: Some(Chain::Ethereum), + authorization_list: None, }, TransactionQueryRes { - transaction_type: Some(2), + r#type: Some(2), hash: Some(b256!( "72546b3ca8ef0dfb85fe66d19645e44cb519858c72fbcad0e1c1699256fed890" )), @@ -268,11 +270,12 @@ mod test { to: Some(address!("2eeb301387d6bda23e02fa0c7463507c68b597b5")), data: Some(bytes!("")), value: Some(U256::from(234808500010631948_u128)), - gas_price: Some(10209184711_u128), - gas: Some(21000), + gas_price: None, + gas_limit: Some(21000), + effective_gas_price: Some(10209184711_u128), status: Some(true), chain_id: Some(1), - v: Some(U256::from(0)), + v: Some(false), r: Some(U256::from_str("105656622829170817033829205634607968479218860016837137132236076370603621041980").unwrap()), s: Some(U256::from_str("15038977765364444198936700207894720753481416564436657360670639019817488048130").unwrap()), max_fee_per_blob_gas: None, @@ -280,6 +283,7 @@ mod test { max_priority_fee_per_gas: Some(0), y_parity: Some(false), chain: Some(Chain::Ethereum), + authorization_list: None, }]) ]; diff --git a/crates/core/src/interpreter/backend/resolve_block.rs b/crates/core/src/interpreter/backend/resolve_block.rs index 811975c..3bbcec5 100644 --- a/crates/core/src/interpreter/backend/resolve_block.rs +++ b/crates/core/src/interpreter/backend/resolve_block.rs @@ -1,12 +1,12 @@ use crate::common::{ - block::{Block, BlockField, BlockId}, + block::{get_block_number_from_tag, Block, BlockField, BlockId}, chain::{Chain, ChainOrRpc}, query_result::BlockQueryRes, }; use alloy::{ eips::BlockNumberOrTag, providers::{Provider, ProviderBuilder, RootProvider}, - rpc::types::Block as RpcBlock, + rpc::types::{Block as RpcBlock, BlockTransactionsKind}, transports::http::{Client, Http}, }; use anyhow::Result; @@ -136,7 +136,13 @@ pub async fn get_block( provider: Arc>>, hydrate: bool, ) -> Result { - match provider.get_block_by_number(block_id, hydrate).await? { + let kind = if hydrate { + BlockTransactionsKind::Full + } else { + BlockTransactionsKind::Hashes + }; + + match provider.get_block_by_number(block_id, kind).await? { Some(block) => Ok(block), None => return Err(BlockResolverErrors::UnableToFetchBlockNumber(block_id.clone()).into()), } @@ -151,16 +157,16 @@ fn filter_fields(block: RpcBlock, fields: &[BlockField], chain: &Chain) -> Block result.timestamp = Some(block.header.timestamp); } BlockField::Number => { - result.number = block.header.number; + result.number = Some(block.header.number); } BlockField::Hash => { - result.hash = block.header.hash; + result.hash = Some(block.header.hash); } BlockField::ParentHash => { result.parent_hash = Some(block.header.parent_hash); } BlockField::Size => { - result.size = block.size; + result.size = block.header.size; } BlockField::StateRoot => { result.state_root = Some(block.header.state_root); @@ -178,7 +184,7 @@ fn filter_fields(block: RpcBlock, fields: &[BlockField], chain: &Chain) -> Block result.extra_data = Some(block.header.extra_data.clone()); } BlockField::MixHash => { - result.mix_hash = block.header.mix_hash; + result.mix_hash = Some(block.header.mix_hash); } BlockField::TotalDifficulty => { result.total_difficulty = block.header.total_difficulty; @@ -207,26 +213,6 @@ fn filter_fields(block: RpcBlock, fields: &[BlockField], chain: &Chain) -> Block result } -async fn get_block_number_from_tag( - provider: Arc>>, - number_or_tag: &BlockNumberOrTag, -) -> Result { - match number_or_tag { - BlockNumberOrTag::Number(number) => Ok(*number), - block_tag => match provider.get_block_by_number(*block_tag, false).await? { - Some(block) => match block.header.number { - Some(number) => Ok(number), - None => { - Err(BlockResolverErrors::UnableToFetchBlockNumber(number_or_tag.clone()).into()) - } - }, - None => { - Err(BlockResolverErrors::UnableToFetchBlockNumber(number_or_tag.clone()).into()) - } - }, - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/core/src/interpreter/backend/resolve_transaction.rs b/crates/core/src/interpreter/backend/resolve_transaction.rs index e657065..4f1ec5c 100644 --- a/crates/core/src/interpreter/backend/resolve_transaction.rs +++ b/crates/core/src/interpreter/backend/resolve_transaction.rs @@ -6,6 +6,7 @@ use crate::common::{ transaction::{Transaction, TransactionField}, }; use alloy::{ + consensus::Transaction as ConsensusTransaction, primitives::FixedBytes, providers::{Provider, ProviderBuilder, RootProvider}, rpc::types::{BlockTransactions, Transaction as RpcTransaction}, @@ -63,7 +64,7 @@ pub async fn resolve_transaction_query( // Filter and collect results for this chain let filtered_tx_res: Vec = tx_res .into_iter() - .filter(|t| transaction.filter(t)) + .filter(|t| t.has_value() && transaction.filter(t)) .collect(); all_results.extend(filtered_tx_res); @@ -79,8 +80,10 @@ async fn get_transactions_by_ids( let mut tx_futures = Vec::new(); for id in ids { let provider = provider.clone(); + // let tx = provider + // .raw_request("eth_getTransactionByHash".into(), (*id,)) + // .await?; let tx_future = async move { provider.get_transaction_by_hash(*id).await }; - tx_futures.push(tx_future); } @@ -128,64 +131,72 @@ async fn pick_transaction_fields( for field in fields { match field { - TransactionField::TransactionType => { - result.transaction_type = tx.transaction_type; + TransactionField::Type => { + result.r#type = Some(tx.inner.tx_type().into()); + } + TransactionField::AuthorizationList => { + result.authorization_list = tx.inner.authorization_list().map(|a| a.to_vec()); } TransactionField::Hash => { - result.hash = Some(tx.hash); + result.hash = Some(tx.inner.tx_hash().clone()); } TransactionField::From => { result.from = Some(tx.from); } TransactionField::To => { - result.to = tx.to; + result.to = tx.inner.to().clone(); } TransactionField::Data => { - result.data = Some(tx.input.clone()); + result.data = Some(tx.inner.input().clone()); } TransactionField::Value => { - result.value = Some(tx.value); + result.value = Some(tx.inner.value().clone()); } TransactionField::GasPrice => { - result.gas_price = tx.gas_price; - } - TransactionField::Gas => { - result.gas = Some(tx.gas); - } - TransactionField::Status => match provider.get_transaction_receipt(tx.hash).await? { - Some(receipt) => { - result.status = Some(receipt.status()); + result.gas_price = tx.inner.gas_price(); + } + TransactionField::EffectiveGasPrice => { + result.effective_gas_price = tx.effective_gas_price; + } + TransactionField::GasLimit => { + result.gas_limit = Some(tx.inner.gas_limit()); + } + TransactionField::Status => { + match provider + .get_transaction_receipt(tx.inner.tx_hash().clone()) + .await? + { + Some(receipt) => { + result.status = Some(receipt.status()); + } + None => { + result.status = None; + } } - None => { - result.status = None; - } - }, + } TransactionField::ChainId => { - result.chain_id = tx.chain_id; + result.chain_id = tx.inner.chain_id(); } TransactionField::V => { - result.v = tx.signature.map_or(None, |s| Some(s.v)); + result.v = Some(tx.inner.signature().v()); } TransactionField::R => { - result.r = tx.signature.map_or(None, |s| Some(s.r)); + result.r = Some(tx.inner.signature().r()); } TransactionField::S => { - result.s = tx.signature.map_or(None, |s| Some(s.s)); + result.s = Some(tx.inner.signature().s()); } TransactionField::MaxFeePerBlobGas => { - result.max_fee_per_blob_gas = tx.max_fee_per_blob_gas; + result.max_fee_per_blob_gas = tx.inner.max_fee_per_blob_gas(); } TransactionField::MaxFeePerGas => { - result.max_fee_per_gas = tx.max_fee_per_gas; + result.max_fee_per_gas = Some(tx.inner.max_fee_per_gas()); } TransactionField::MaxPriorityFeePerGas => { - result.max_priority_fee_per_gas = tx.max_priority_fee_per_gas; + result.max_priority_fee_per_gas = tx.inner.max_priority_fee_per_gas(); } TransactionField::YParity => { - result.y_parity = tx - .signature - .map_or(None, |s| s.y_parity) - .map_or(None, |y| Some(y.0)); + result.y_parity = Some(tx.inner.signature().v()); } TransactionField::Chain => { result.chain = Some(chain.clone()); @@ -195,112 +206,3 @@ async fn pick_transaction_fields( Ok(result) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::common::{ - block::BlockRange, - chain::Chain, - filters::{ComparisonFilter, EqualityFilter, FilterType}, - transaction::TransactionFilter, - }; - use alloy::{ - eips::BlockNumberOrTag, - primitives::{address, U256}, - providers::ProviderBuilder, - }; - - #[tokio::test] - async fn test_get_transactions_by_block_range() { - let rpc = Chain::Ethereum.rpc_url().unwrap(); - let provider = Arc::new(ProviderBuilder::new().on_http(rpc)); - let block_id = BlockId::Range(BlockRange::new(10000000.into(), Some(10000015.into()))); - let transactions = get_transactions_by_block_id(&block_id, &provider) - .await - .unwrap(); - - assert_eq!(transactions.len(), 2394); - } - - #[tokio::test] - async fn test_get_transactions_by_block_number() { - let rpc = Chain::Ethereum.rpc_url().unwrap(); - let provider = Arc::new(ProviderBuilder::new().on_http(rpc)); - let block_id = BlockId::Number(BlockNumberOrTag::Number(21036202)); - let transactions = get_transactions_by_block_id(&block_id, &provider) - .await - .unwrap(); - - assert_eq!(transactions.len(), 177); - } - - #[tokio::test] - async fn test_resolve_query_using_block_range_filter() { - let rpc = Chain::Ethereum.rpc_url().unwrap(); - let chain = ChainOrRpc::Rpc(rpc); - let block_id = BlockId::Range(BlockRange::new(10000000.into(), Some(10000001.into()))); - let transaction = Transaction::new( - None, - Some(vec![TransactionFilter::BlockId(block_id)]), - TransactionField::all_variants().to_vec(), - ); - - let transactions = resolve_transaction_query(&transaction, &[chain]) - .await - .unwrap(); - - assert_eq!(transactions.len(), 211); - } - - #[tokio::test] - async fn test_resolve_query_using_filters() { - let value = "1000000000000000".parse::().unwrap(); - let from = address!("BF2EFaA8715d75AfC562Cde29f56B55aA0Fb219F"); - let to = address!("3fE873889008521bf335E07CEAfdfd0D9a6864A8"); - let gas = 22000; - let gas_price = 5000000000; - let status = true; - - let chain = ChainOrRpc::Chain(Chain::Ethereum); - let block_id = BlockId::Range(BlockRange::new(10000004.into(), None)); - let transaction = Transaction::new( - None, - Some(vec![ - TransactionFilter::BlockId(block_id), - TransactionFilter::Value(FilterType::Comparison(ComparisonFilter::Lte(value))), - TransactionFilter::From(EqualityFilter::Eq(from)), - TransactionFilter::To(EqualityFilter::Eq(to)), - TransactionFilter::Gas(FilterType::Comparison(ComparisonFilter::Lte(gas))), - TransactionFilter::GasPrice(FilterType::Comparison(ComparisonFilter::Lte( - gas_price, - ))), - TransactionFilter::Status(EqualityFilter::Eq(status)), - ]), - TransactionField::all_variants().to_vec(), - ); - - let transactions = resolve_transaction_query(&transaction, &[chain]) - .await - .unwrap(); - - let tx = transactions.first().unwrap(); - let expected_tx: TransactionQueryRes = TransactionQueryRes { - value: Some(value), - from: Some(from), - to: Some(to), - gas: Some(gas), - gas_price: Some(gas_price), - status: Some(status), - ..Default::default() - }; - - assert_eq!(transactions.len(), 1); - assert_eq!(tx.value, expected_tx.value); - assert_eq!(tx.from, expected_tx.from); - assert_eq!(tx.to, expected_tx.to); - assert_eq!(tx.gas, expected_tx.gas); - assert_eq!(tx.gas_price, expected_tx.gas_price); - assert_eq!(tx.status, expected_tx.status); - } -} diff --git a/crates/core/src/interpreter/frontend/parser.rs b/crates/core/src/interpreter/frontend/parser.rs index 44ae970..caa8195 100644 --- a/crates/core/src/interpreter/frontend/parser.rs +++ b/crates/core/src/interpreter/frontend/parser.rs @@ -198,9 +198,9 @@ mod tests { #[test] fn test_build_ast_with_transaction_fields() { - let source = "GET transaction_type, hash, from, to, data, value, gas_price, gas, \ + let source = "GET type, hash, from, to, data, value, gas_price, gas_limit, \ status, v, r, s, max_fee_per_blob_gas, max_fee_per_gas, \ - max_priority_fee_per_gas, y_parity \ + max_priority_fee_per_gas, y_parity, authorization_list \ FROM tx 0x8a6a279a4d28dcc62bcb2f2a3214c93345c107b74f3081754e27471c50783f81 \ ON eth"; @@ -211,14 +211,14 @@ mod tests { )]), None, vec![ - TransactionField::TransactionType, + TransactionField::Type, TransactionField::Hash, TransactionField::From, TransactionField::To, TransactionField::Data, TransactionField::Value, TransactionField::GasPrice, - TransactionField::Gas, + TransactionField::GasLimit, TransactionField::Status, TransactionField::V, TransactionField::R, @@ -227,6 +227,7 @@ mod tests { TransactionField::MaxFeePerGas, TransactionField::MaxPriorityFeePerGas, TransactionField::YParity, + TransactionField::AuthorizationList, ], )), chains: vec![ChainOrRpc::Chain(Chain::Ethereum)], @@ -388,7 +389,7 @@ mod tests { fn test_build_ast_with_transaction_comparison_filters() { let source = "GET * FROM tx WHERE \ block = 4638757, \ - gas > 10000000, \ + gas_limit > 10000000, \ gas_price < 10000000, \ max_fee_per_blob_gas >= 10000000, \ max_fee_per_gas <= 10000000, \ @@ -408,7 +409,7 @@ mod tests { BlockNumberOrTag::Number(4638757), None, ))), - TransactionFilter::Gas(FilterType::Comparison(ComparisonFilter::Gt( + TransactionFilter::GasLimit(FilterType::Comparison(ComparisonFilter::Gt( U128::from(10000000).try_into().unwrap(), ))), TransactionFilter::GasPrice(FilterType::Comparison(ComparisonFilter::Lt( diff --git a/crates/core/src/interpreter/frontend/productions.pest b/crates/core/src/interpreter/frontend/productions.pest index aea2dff..d7c8924 100644 --- a/crates/core/src/interpreter/frontend/productions.pest +++ b/crates/core/src/interpreter/frontend/productions.pest @@ -116,7 +116,7 @@ block_filter = { blockrange_filter } // Transaction tx_field_list = _{ tx_field ~ ("," ~ WHITESPACE* ~ tx_field)* } tx_field = { - "transaction_type" | + "type" | "hash" | "from" | "to" | @@ -124,13 +124,17 @@ tx_field = { "value" | "fee" | "gas_price" | - "gas" | + "gas_limit" | + "effective_gas_price" | "status" | "chain_id" | "v" | "r" | "s" | + // EIP-7702 + "authorization_list" | + // EIP-4844 "max_fee_per_blob_gas" | "blob_versioned_hashes" | @@ -149,13 +153,15 @@ tx_id = { hash } // Transaction filters tx_filter_list = _{ "WHERE" ~ WHITESPACE* ~ tx_filter ~ ("," ~ WHITESPACE* ~ tx_filter)* } tx_filter = { + type_filter | blockrange_filter | from_filter | to_filter | data_filter | value_filter | gas_price_filter | - gas_filter | + effective_gas_price_filter | + gas_limit_filter | status_filter | max_fee_per_blob_gas_filter | blob_versioned_hashes_filter | @@ -164,12 +170,14 @@ tx_filter = { y_parity_filter } +type_filter_type = { equality_operators ~ number } from_filter_type = { equality_operators ~ address | ens } to_filter_type = { equality_operators ~ address } data_filter_type = { equality_operators ~ hex_string } value_filter_type = { all_operators ~ number } -gas_filter_type = { all_operators ~ number } +gas_limit_filter_type = { all_operators ~ number } gas_price_filter_type = { all_operators ~ number } +effective_gas_price_filter_type = { all_operators ~ number } status_filter_type = { equality_operators ~ boolean } max_fee_per_blob_gas_filter_type = { all_operators ~ number } blob_versioned_hashes_filter_type = { equality_operators ~ hex_string } @@ -178,13 +186,15 @@ max_priority_fee_per_gas_filter_type = { all_operators ~ number } y_parity_filter_type = { equality_operators ~ boolean } // TODO: add support for different ether units (ether, gwei, wei) +type_filter = _{ "type" ~ type_filter_type } from_filter = _{"from" ~ from_filter_type} to_filter = _{"to" ~ to_filter_type} data_filter = _{"data" ~ data_filter_type} value_filter = _{"value" ~ value_filter_type} gas_price_filter = _{"gas_price" ~ gas_price_filter_type} -gas_filter = _{"gas" ~ gas_filter_type} +gas_limit_filter = _{"gas_limit" ~ gas_limit_filter_type} status_filter = _{"status" ~ status_filter_type} +effective_gas_price_filter = _{"effective_gas_price" ~ effective_gas_price_filter_type} max_fee_per_blob_gas_filter = _{"max_fee_per_blob_gas" ~ max_fee_per_blob_gas_filter_type} blob_versioned_hashes_filter = _{"blob_versioned_hashes" ~ blob_versioned_hashes_filter_type} max_fee_per_gas_filter = _{"max_fee_per_gas" ~ max_fee_per_gas_filter_type} @@ -312,4 +322,4 @@ wildcard = { "*" } // Add new rules for chain selection chain_selector = { chain_list | chain_wildcard } chain_list = { chain ~ ("," ~ WHITESPACE* ~ chain)* } -chain_wildcard = { "*" } \ No newline at end of file +chain_wildcard = { "*" } diff --git a/docs/query.md b/docs/query.md index 536314a..bf564d2 100644 --- a/docs/query.md +++ b/docs/query.md @@ -126,8 +126,8 @@ Transactions supports the following identifiers: - `data`: Transaction input data - `nonce`: Transaction nonce - `gas_price`: Gas price in wei -- `gas`: Gas limit -- `transaction_type`: Transaction type +- `gas_limit`: Gas limit +- `type`: Transaction type - `fee`: Transaction fee in wei - `status`: Transaction status (true = success, false = failure) - `v`: v component of signature diff --git a/examples/get-transaction.eql b/examples/get-transaction.eql index 88f0cdd..a48e375 100644 --- a/examples/get-transaction.eql +++ b/examples/get-transaction.eql @@ -1 +1 @@ -GET from, to, value, fee, timestamp FROM tx 0xa9e39789f09753e7afa0838c52e3dd332627f1b18eec07e1652ede6f5a958fa1 ON eth +GET authorization_list FROM tx WHERE block = 45090 ON mekong \ No newline at end of file From 96a8f31e9595dc5f0b933af70486c053ab3b6a19 Mon Sep 17 00:00:00 2001 From: "Ian K. Guimaraes" Date: Wed, 13 Nov 2024 18:36:44 -0300 Subject: [PATCH 2/2] chore: bump eql_core version --- Cargo.lock | 2 +- crates/core/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9e5e2f..7f7a147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "eql_core" -version = "0.1.19" +version = "0.1.20" dependencies = [ "alloy", "alloy-eip7702", diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 356ff24..66b3c5e 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "eql_core" -version = "0.1.19" +version = "0.1.20" rust-version.workspace = true edition.workspace = true authors.workspace = true