From d40bb7cb78b47795295127b7ae30180bb4ec7440 Mon Sep 17 00:00:00 2001 From: Ion Suman <47307091+isum@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:55:54 +0200 Subject: [PATCH 01/44] migrate from `ethabi` to `alloy` --- Cargo.lock | 1459 ++++++++++++++++- Cargo.toml | 1 + chain/ethereum/src/adapter.rs | 21 +- chain/ethereum/src/data_source.rs | 100 +- chain/ethereum/src/ethereum_adapter.rs | 42 +- chain/ethereum/src/ingestor.rs | 4 +- chain/ethereum/src/runtime/abi.rs | 6 +- chain/ethereum/src/runtime/runtime_adapter.rs | 64 +- chain/ethereum/src/trigger.rs | 40 +- graph/Cargo.toml | 1 + graph/src/abi/event_ext.rs | 181 ++ graph/src/abi/function_ext.rs | 303 ++++ graph/src/abi/mod.rs | 20 + graph/src/abi/param.rs | 7 + graph/src/abi/value_ext.rs | 277 ++++ graph/src/cheap_clone.rs | 2 +- graph/src/components/store/mod.rs | 2 +- graph/src/data/store/ethereum.rs | 4 +- graph/src/data_source/common.rs | 168 +- graph/src/lib.rs | 4 +- runtime/test/src/common.rs | 6 +- runtime/test/src/test/abi.rs | 37 +- runtime/wasm/Cargo.toml | 1 - runtime/wasm/src/asc_abi/class.rs | 31 +- runtime/wasm/src/host_exports.rs | 19 +- runtime/wasm/src/to_from/external.rs | 95 +- store/postgres/src/chain_store.rs | 2 +- store/test-store/Cargo.toml | 1 + store/test-store/tests/postgres/store.rs | 24 +- tests/src/fixture/ethereum.rs | 17 +- tests/src/fixture/mod.rs | 2 +- tests/tests/runner_tests.rs | 2 +- 32 files changed, 2563 insertions(+), 380 deletions(-) create mode 100644 graph/src/abi/event_ext.rs create mode 100644 graph/src/abi/function_ext.rs create mode 100644 graph/src/abi/mod.rs create mode 100644 graph/src/abi/param.rs create mode 100644 graph/src/abi/value_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 25bde667ebf..4d0d79f8bf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,570 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2cc5aeb8dfa1e451a49fac87bc4b86c5de40ebea153ed88e83eb92b8151e74" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum 0.27.1", +] + +[[package]] +name = "alloy-consensus" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e32ef5c74bbeb1733c37f4ac7f866f8c8af208b7b4265e21af609dcac5bd5e" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "auto_impl", + "c-kzg", + "derive_more 1.0.0", + "serde", +] + +[[package]] +name = "alloy-consensus-any" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa13b7b1e1e3fedc42f0728103bfa3b4d566d3d42b606db449504d88dbdbdcf" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6180fb232becdea70fad57c63b6967f01f74ab9595671b870f504116dd29de" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures 0.3.31", + "futures-util", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-core" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8bcce99ad10fe02640cfaec1c6bc809b837c783c1d52906aa5af66e2a196f6" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb8e762aefd39a397ff485bc86df673465c4ad3ec8819cc60833a8a3ba5cdc87" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.7.9", +] + +[[package]] +name = "alloy-eip2124" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675264c957689f0fd75f5993a73123c2cc3b5c235a38f5b9037fe6c826bfb2c0" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "crc", + "thiserror 2.0.12", +] + +[[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.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-eips" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5591581ca2ab0b3e7226a4047f9a1bfcf431da1d0cce3752fda609fea3c27e37" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 1.0.0", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cded3a2d4bd7173f696458c5d4c98c18a628dfcc9f194385e80a486e412e2e0" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6beff64ad0aa6ad1019a3db26fef565aefeb011736150ab73ed3366c3cfd1b" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "762414662d793d7aaa36ee3af6928b6be23227df1681ce9c039f6f11daadef64" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror 2.0.12", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be03f2ebc00cf88bd06d3c6caf387dceaa9c7e6b268216779fa68a9bf8ab4e6" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a00ce618ae2f78369918be0c20f620336381502c83b6ed62c2f7b2db27698b0" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if 1.0.0", + "const-hex", + "derive_more 2.0.1", + "foldhash", + "hashbrown 0.15.2", + "indexmap 2.9.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash 2.1.1", + "serde", + "sha3", + "tiny-keccak 2.0.2", +] + +[[package]] +name = "alloy-provider" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbe0a2acff0c4bd1669c71251ce10fc455cbffa1b4d0a817d5ea4ba7e5bb3db7" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures 0.3.31", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.12", + "tokio", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" +dependencies = [ + "alloy-rlp-derive", + "arrayvec 0.7.4", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b37cc3c7883dc41be1b01460127ad7930466d0a4bb6ba15a02ee34d2745e2d7c" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures 0.3.31", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f18e68a3882f372e045ddc89eb455469347767d17878ca492cfbac81e71a111" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "318ae46dd12456df42527c3b94c1ae9001e1ceb707f7afe2c7807ac4e49ebad9" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4dbee4d82f8a22dde18c28257bed759afeae7ba73da4a1479a039fd1445d04" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-serde" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8732058f5ca28c1d53d241e8504620b997ef670315d7c8afab856b3e3b80d945" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f96b3526fdd779a4bd0f37319cfb4172db52a7ac24cdbb8804b72091c18e1701" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-signer-local" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8f78cd6b7501c7e813a1eb4a087b72d23af51f5bb66d4e948dc840bdd207d8" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10ae8e9a91d328ae954c22542415303919aabe976fe7a92eb06db1b68fd59f2" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83ad5da86c127751bc607c174d6c9fe9b85ef0889a9ca0c641735d77d4f98f26" +dependencies = [ + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap 2.9.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.101", + "syn-solidity", + "tiny-keccak 2.0.2", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3d30f0d3f9ba3b7686f3ff1de9ee312647aac705604417a2f40c604f409a9e" +dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck 0.5.0", + "macro-string", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.101", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" +dependencies = [ + "serde", + "winnow 0.7.9", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43d5e60466a440230c07761aa67671d4719d46f43be8ea6e7ed334d8db4a9ab" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a8d762eadce3e9b65eac09879430c6f4fce3736cac3cac123f9b1bf435ddd13" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.1", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.12", + "tokio", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20819c4cb978fb39ce6ac31991ba90f386d595f922f42ef888b4a18be190713e" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "url", +] + +[[package]] +name = "alloy-trie" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec 0.7.4", + "derive_more 1.0.0", + "nybbles", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -97,41 +661,165 @@ dependencies = [ ] [[package]] -name = "anstyle-query" -version = "1.1.0" +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "windows-sys 0.52.0", + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "anstyle-wincon" -version = "3.0.3" +name = "ark-serialize" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" dependencies = [ - "anstyle", - "windows-sys 0.52.0", + "ark-std 0.3.0", + "digest 0.9.0", ] [[package]] -name = "anyhow" -version = "1.0.98" +name = "ark-serialize" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint 0.4.6", +] [[package]] -name = "arbitrary" -version = "1.4.1" +name = "ark-std" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] -name = "arc-swap" -version = "1.7.1" +name = "ark-std" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] name = "arrayref" @@ -150,6 +838,9 @@ name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +dependencies = [ + "serde", +] [[package]] name = "ascii" @@ -236,7 +927,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "strum", + "strum 0.26.3", "syn 2.0.101", "thiserror 1.0.61", ] @@ -332,6 +1023,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -472,6 +1174,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" @@ -490,6 +1198,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" + [[package]] name = "beef" version = "0.5.2" @@ -522,6 +1236,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -592,6 +1321,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bs58" version = "0.4.0" @@ -647,6 +1388,21 @@ dependencies = [ "serde", ] +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + [[package]] name = "cc" version = "1.2.16" @@ -790,6 +1546,25 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "const-hex" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -927,7 +1702,7 @@ dependencies = [ "log", "pulley-interpreter", "regalloc2", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "serde", "smallvec", "target-lexicon", @@ -1006,6 +1781,21 @@ version = "0.120.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85256fac1519a7d25a040c1d850fba67478f3f021ad5fdf738ba4425ee862dbf" +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -1077,6 +1867,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1153,6 +1955,20 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -1212,6 +2028,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "930c7171c8df9fb1782bdf9b918ed9ed2d33d1d22300abb754f9085bc48bf8e8" +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1242,17 +2068,37 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.0", "syn 2.0.101", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + [[package]] name = "derive_more" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ - "derive_more-impl", + "derive_more-impl 2.0.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -1370,6 +2216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -1451,12 +2298,51 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embedded-io" version = "0.4.0" @@ -1567,7 +2453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" dependencies = [ "crunchy", - "fixed-hash", + "fixed-hash 0.7.0", "impl-rlp", "impl-serde", "tiny-keccak 2.0.2", @@ -1580,10 +2466,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" dependencies = [ "ethbloom", - "fixed-hash", + "fixed-hash 0.7.0", "impl-rlp", "impl-serde", - "primitive-types", + "primitive-types 0.11.1", "uint 0.9.5", ] @@ -1614,6 +2500,38 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec 0.7.4", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec 0.7.4", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "firestorm" version = "0.4.6" @@ -1638,6 +2556,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fixedbitset" version = "0.5.7" @@ -1798,6 +2728,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1828,6 +2764,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1892,6 +2829,12 @@ dependencies = [ "time", ] +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + [[package]] name = "globset" version = "0.4.14" @@ -1910,6 +2853,7 @@ name = "graph" version = "0.36.0" dependencies = [ "Inflector", + "alloy", "anyhow", "async-stream", "async-trait", @@ -1941,7 +2885,7 @@ dependencies = [ "humantime", "hyper 1.6.0", "hyper-util", - "itertools", + "itertools 0.14.0", "lazy_static", "lru_time_cache", "maplit", @@ -1959,7 +2903,7 @@ dependencies = [ "redis", "regex", "reqwest", - "semver", + "semver 1.0.23", "serde", "serde_derive", "serde_json", @@ -2010,11 +2954,11 @@ dependencies = [ "graph-runtime-derive", "graph-runtime-wasm", "hex", - "itertools", + "itertools 0.14.0", "jsonrpc-core", "prost", "prost-types", - "semver", + "semver 1.0.23", "serde", "thiserror 2.0.12", "tiny-keccak 1.5.0", @@ -2049,7 +2993,7 @@ dependencies = [ "lazy_static", "prost", "prost-types", - "semver", + "semver 1.0.23", "serde", "tokio", "tonic-build", @@ -2113,7 +3057,7 @@ dependencies = [ "graph-store-postgres", "graphman", "graphman-server", - "itertools", + "itertools 0.14.0", "json-structural-diff", "lazy_static", "prometheus", @@ -2142,7 +3086,7 @@ dependencies = [ "graph-runtime-derive", "graph-runtime-wasm", "rand 0.9.1", - "semver", + "semver 1.0.23", "test-store", "wasmtime", ] @@ -2154,13 +3098,12 @@ dependencies = [ "anyhow", "async-trait", "bs58 0.4.0", - "ethabi", "graph", "graph-runtime-derive", "hex", "never", "parity-wasm", - "semver", + "semver 1.0.23", "serde_yaml", "wasm-instrument", "wasmtime", @@ -2227,7 +3170,7 @@ dependencies = [ "graphman-store", "graphql-parser", "hex", - "itertools", + "itertools 0.14.0", "lazy_static", "lru_time_cache", "maybe-owned", @@ -2285,7 +3228,7 @@ dependencies = [ "graph", "graph-store-postgres", "graphman-store", - "itertools", + "itertools 0.14.0", "thiserror 2.0.12", "tokio", ] @@ -2322,7 +3265,7 @@ dependencies = [ "anyhow", "chrono", "diesel", - "strum", + "strum 0.26.3", ] [[package]] @@ -2348,6 +3291,17 @@ dependencies = [ "serde_with", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "h2" version = "0.3.26" @@ -2406,6 +3360,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.2" @@ -2484,6 +3444,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-literal" @@ -2980,6 +3943,15 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -3132,6 +4104,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + [[package]] name = "keccak" version = "0.1.5" @@ -3141,6 +4126,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -3167,9 +4162,9 @@ checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "a25169bd5913a4b437588a7e3d127cd6e90127b60e0ffbd834a38f1599e016b8" [[package]] name = "libredox" @@ -3215,6 +4210,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +dependencies = [ + "hashbrown 0.15.2", +] + [[package]] name = "lru_time_cache" version = "0.11.11" @@ -3230,6 +4234,17 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "maplit" version = "1.0.2" @@ -3453,6 +4468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3465,6 +4481,39 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "nybbles" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + [[package]] name = "object" version = "0.36.7" @@ -3493,7 +4542,7 @@ dependencies = [ "http-body-util", "humantime", "hyper 1.6.0", - "itertools", + "itertools 0.14.0", "parking_lot", "percent-encoding", "quick-xml", @@ -3637,6 +4686,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -3760,6 +4815,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -3880,13 +4945,24 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ - "fixed-hash", + "fixed-hash 0.7.0", "impl-codec", "impl-rlp", "impl-serde", "uint 0.9.5", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", + "impl-codec", + "uint 0.9.5", +] + [[package]] name = "priority-queue" version = "2.3.1" @@ -3907,6 +4983,28 @@ dependencies = [ "toml_edit 0.21.1", ] +[[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.101", +] + [[package]] name = "proc-macro-utils" version = "0.10.0" @@ -3944,6 +5042,26 @@ dependencies = [ "thiserror 1.0.61", ] +[[package]] +name = "proptest" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "prost" version = "0.13.5" @@ -3961,7 +5079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ "heck 0.5.0", - "itertools", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -3981,7 +5099,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.101", @@ -4058,6 +5176,12 @@ dependencies = [ "wasmtime-math", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-xml" version = "0.37.5" @@ -4094,7 +5218,7 @@ dependencies = [ "bytes", "rand 0.8.5", "ring", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "rustls", "slab", "thiserror 1.0.61", @@ -4150,6 +5274,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -4200,6 +5325,15 @@ dependencies = [ "getrandom 0.3.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rayon" version = "1.10.0" @@ -4284,7 +5418,7 @@ dependencies = [ "bumpalo", "hashbrown 0.15.2", "log", - "rustc-hash 2.0.0", + "rustc-hash 2.1.1", "smallvec", ] @@ -4370,6 +5504,16 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.13" @@ -4394,6 +5538,39 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "ruint" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a46eb779843b2c4f21fac5773e25d6d5b7c8f0922876c91541790d2ca27eef" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types 0.12.2", + "proptest", + "rand 0.8.5", + "rand 0.9.1", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4408,9 +5585,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-hex" @@ -4418,13 +5595,22 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.23", ] [[package]] @@ -4526,6 +5712,18 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.18" @@ -4565,6 +5763,20 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.21.3" @@ -4619,6 +5831,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.23" @@ -4628,6 +5849,15 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.219" @@ -4803,6 +6033,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if 1.0.0", +] + [[package]] name = "shellexpand" version = "3.1.0" @@ -4827,6 +6067,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -4950,6 +6200,16 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sptr" version = "0.3.2" @@ -5037,6 +6297,15 @@ dependencies = [ "strum_macros 0.26.4", ] +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros 0.27.1", +] + [[package]] name = "strum_macros" version = "0.26.4" @@ -5169,6 +6438,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4560533fbd6914b94a8fb5cc803ed6801c3455668db3b810702c57612bac9412" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -5291,6 +6572,7 @@ dependencies = [ "lazy_static", "pretty_assertions", "prost-types", + "serde_json", ] [[package]] @@ -5343,6 +6625,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.36" @@ -5900,6 +7191,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.7.0" @@ -6034,6 +7331,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcpkg" version = "0.2.15" @@ -6052,6 +7355,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -6211,7 +7523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" dependencies = [ "indexmap 2.9.0", - "semver", + "semver 1.0.23", ] [[package]] @@ -6223,7 +7535,7 @@ dependencies = [ "bitflags 2.6.0", "hashbrown 0.15.2", "indexmap 2.9.0", - "semver", + "semver 1.0.23", "serde", ] @@ -6235,7 +7547,7 @@ checksum = "b51cb03afce7964bbfce46602d6cb358726f36430b6ba084ac6020d8ce5bc102" dependencies = [ "bitflags 2.6.0", "indexmap 2.9.0", - "semver", + "semver 1.0.23", ] [[package]] @@ -6279,7 +7591,7 @@ dependencies = [ "pulley-interpreter", "rayon", "rustix 1.0.7", - "semver", + "semver 1.0.23", "serde", "serde_derive", "serde_json", @@ -6370,7 +7682,7 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "gimli 0.31.1", - "itertools", + "itertools 0.14.0", "log", "object", "pulley-interpreter", @@ -6398,7 +7710,7 @@ dependencies = [ "object", "postcard", "rustc-demangle", - "semver", + "semver 1.0.23", "serde", "serde_derive", "smallvec", @@ -6503,6 +7815,20 @@ dependencies = [ "wit-parser", ] +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures 0.3.31", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "wast" version = "233.0.0" @@ -6929,6 +8255,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +dependencies = [ + "memchr", +] + [[package]] name = "wiremock" version = "0.6.3" @@ -6972,7 +8307,7 @@ dependencies = [ "id-arena", "indexmap 2.9.0", "log", - "semver", + "semver 1.0.23", "serde", "serde_derive", "serde_json", @@ -7063,6 +8398,20 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] [[package]] name = "zerovec" diff --git a/Cargo.toml b/Cargo.toml index 2ec70e254ee..72eb515e309 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ repository = "https://github.com/graphprotocol/graph-node" license = "MIT OR Apache-2.0" [workspace.dependencies] +alloy = { version = "0.11.1", features = ["dyn-abi", "json-abi"] } anyhow = "1.0" async-graphql = { version = "7.0.15", features = ["chrono"] } async-graphql-axum = "7.0.15" diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 93a7fc60781..47ea9950e3d 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1,5 +1,5 @@ use anyhow::Error; -use ethabi::{Error as ABIError, ParamType, Token}; +use graph::abi; use graph::blockchain::ChainIdentifier; use graph::components::subgraph::MappingError; use graph::data::store::ethereum::call; @@ -101,13 +101,12 @@ pub enum EthereumRpcError { #[derive(Error, Debug)] pub enum ContractCallError { - #[error("ABI error: {0}")] - ABIError(#[from] ABIError), - /// `Token` is not of expected `ParamType` - #[error("type mismatch, token {0:?} is not of kind {1:?}")] - TypeError(Token, ParamType), - #[error("error encoding input call data: {0}")] - EncodingError(ethabi::Error), + #[error("ABI error: {0:#}")] + ABIError(anyhow::Error), + #[error("type mismatch, decoded value {0:?} is not of kind {1:?}")] + TypeError(abi::DynSolValue, abi::DynSolType), + #[error("error encoding input call data: {0:#}")] + EncodingError(anyhow::Error), #[error("call error: {0}")] Web3Error(web3::Error), #[error("ethereum node took too long to perform call")] @@ -1157,7 +1156,7 @@ pub trait EthereumAdapter: Send + Sync + 'static { logger: &Logger, call: &ContractCall, cache: Arc, - ) -> Result<(Option>, call::Source), ContractCallError>; + ) -> Result<(Option>, call::Source), ContractCallError>; /// Make multiple contract calls in a single batch. The returned `Vec` /// has results in the same order as the calls in `calls` on input. The @@ -1167,7 +1166,7 @@ pub trait EthereumAdapter: Send + Sync + 'static { logger: &Logger, calls: &[&ContractCall], cache: Arc, - ) -> Result>, call::Source)>, ContractCallError>; + ) -> Result>, call::Source)>, ContractCallError>; async fn get_balance( &self, @@ -1196,9 +1195,9 @@ mod tests { use graph::blockchain::TriggerFilter as _; use graph::firehose::{CallToFilter, CombinedFilter, LogFilter, MultiLogFilter}; use graph::petgraph::graphmap::GraphMap; - use graph::prelude::ethabi::ethereum_types::H256; use graph::prelude::web3::types::Address; use graph::prelude::web3::types::Bytes; + use graph::prelude::web3::types::H256; use graph::prelude::EthereumCall; use hex::ToHex; use itertools::Itertools; diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index a2da3e6cb4e..551ee21f246 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -1,5 +1,8 @@ use anyhow::{anyhow, Error}; use anyhow::{ensure, Context}; +use graph::abi; +use graph::abi::EventExt; +use graph::abi::FunctionExt; use graph::blockchain::{BlockPtr, TriggerWithHandler}; use graph::components::metrics::subgraph::SubgraphInstanceMetrics; use graph::components::store::{EthereumCallCache, StoredDynamicDataSource}; @@ -13,8 +16,8 @@ use graph::env::ENV_VARS; use graph::futures03::future::try_join; use graph::futures03::stream::FuturesOrdered; use graph::futures03::TryStreamExt; -use graph::prelude::ethabi::ethereum_types::H160; -use graph::prelude::ethabi::StateMutability; +use graph::prelude::web3::types::Address; +use graph::prelude::web3::types::H160; use graph::prelude::{Link, SubgraphManifestValidationError}; use graph::slog::{debug, error, o, trace}; use itertools::Itertools; @@ -30,9 +33,7 @@ use tiny_keccak::{keccak256, Keccak}; use graph::{ blockchain::{self, Blockchain}, prelude::{ - async_trait, - ethabi::{Address, Event, Function, LogParam, ParamType, RawLog}, - serde_json, warn, + async_trait, serde_json, warn, web3::types::{Log, Transaction, H256}, BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, LinkResolver, Logger, @@ -525,28 +526,28 @@ impl DataSource { } } - /// Returns the contract event with the given signature, if it exists. A an event from the ABI + /// Returns the contract event with the given signature, if it exists. An event from the ABI /// will be matched if: /// 1. An event signature is equal to `signature`. /// 2. There are no equal matches, but there is exactly one event that equals `signature` if all /// `indexed` modifiers are removed from the parameters. - fn contract_event_with_signature(&self, signature: &str) -> Option<&Event> { + fn contract_event_with_signature(&self, signature: &str) -> Option<&abi::Event> { // Returns an `Event(uint256,address)` signature for an event, without `indexed` hints. - fn ambiguous_event_signature(event: &Event) -> String { + fn ambiguous_event_signature(event: &abi::Event) -> String { format!( "{}({})", event.name, event .inputs .iter() - .map(|input| event_param_type_signature(&input.kind)) + .map(|input| input.selector_type().into_owned()) .collect::>() .join(",") ) } // Returns an `Event(indexed uint256,address)` type signature for an event. - fn event_signature(event: &Event) -> String { + fn event_signature(event: &abi::Event) -> String { format!( "{}({})", event.name, @@ -556,40 +557,13 @@ impl DataSource { .map(|input| format!( "{}{}", if input.indexed { "indexed " } else { "" }, - event_param_type_signature(&input.kind) + input.selector_type() )) .collect::>() .join(",") ) } - // Returns the signature of an event parameter type (e.g. `uint256`). - fn event_param_type_signature(kind: &ParamType) -> String { - use ParamType::*; - - match kind { - Address => "address".into(), - Bytes => "bytes".into(), - Int(size) => format!("int{}", size), - Uint(size) => format!("uint{}", size), - Bool => "bool".into(), - String => "string".into(), - Array(inner) => format!("{}[]", event_param_type_signature(inner)), - FixedBytes(size) => format!("bytes{}", size), - FixedArray(inner, size) => { - format!("{}[{}]", event_param_type_signature(inner), size) - } - Tuple(components) => format!( - "({})", - components - .iter() - .map(event_param_type_signature) - .collect::>() - .join(",") - ), - } - } - self.contract_abi .contract .events() @@ -628,7 +602,9 @@ impl DataSource { }) } - fn contract_function_with_signature(&self, target_signature: &str) -> Option<&Function> { + fn contract_function_with_signature(&self, target_signature: &str) -> Option<&abi::Function> { + use abi::StateMutability; + self.contract_abi .contract .functions() @@ -642,7 +618,7 @@ impl DataSource { let mut arguments = function .inputs .iter() - .map(|input| format!("{}", input.kind)) + .map(|input| input.selector_type().into_owned()) .collect::>() .join(","); // `address,uint256,bool) @@ -732,11 +708,7 @@ impl DataSource { .into_iter() .filter_map(|(event_handler, event_abi)| { event_abi - .parse_log(RawLog { - topics: log.topics.clone(), - data: log.data.clone().0, - }) - .map(|log| log.params) + .decode_log(&log) .map_err(|e| { trace!( logger, @@ -841,20 +813,15 @@ impl DataSource { ) })?; - // Parse the inputs - // - // Take the input for the call, chop off the first 4 bytes, then call - // `function.decode_input` to get a vector of `Token`s. Match the `Token`s - // with the `Param`s in `function.inputs` to create a `Vec`. - let tokens = match function_abi.decode_input(&call.input.0[4..]).with_context( - || { + let values = match function_abi + .abi_decode_input(&call.input.0[4..]) + .with_context(|| { format!( "Generating function inputs for the call {:?} failed, raw input: {}", &function_abi, hex::encode(&call.input.0) ) - }, - ) { + }) { Ok(val) => val, // See also 280b0108-a96e-4738-bb37-60ce11eeb5bf Err(err) => { @@ -864,27 +831,22 @@ impl DataSource { }; ensure!( - tokens.len() == function_abi.inputs.len(), + values.len() == function_abi.inputs.len(), "Number of arguments in call does not match \ number of inputs in function signature." ); - let inputs = tokens + let inputs = values .into_iter() .enumerate() - .map(|(i, token)| LogParam { + .map(|(i, value)| abi::DynSolParam { name: function_abi.inputs[i].name.clone(), - value: token, + value, }) .collect::>(); - // Parse the outputs - // - // Take the output for the call, then call `function.decode_output` to - // get a vector of `Token`s. Match the `Token`s with the `Param`s in - // `function.outputs` to create a `Vec`. - let tokens = function_abi - .decode_output(&call.output.0) + let values = function_abi + .abi_decode_output(&call.output.0) .with_context(|| { format!( "Decoding function outputs for the call {:?} failed, raw output: {}", @@ -894,17 +856,17 @@ impl DataSource { })?; ensure!( - tokens.len() == function_abi.outputs.len(), + values.len() == function_abi.outputs.len(), "Number of parameters in the call output does not match \ number of outputs in the function signature." ); - let outputs = tokens + let outputs = values .into_iter() .enumerate() - .map(|(i, token)| LogParam { + .map(|(i, value)| abi::DynSolParam { name: function_abi.outputs[i].name.clone(), - value: token, + value, }) .collect::>(); diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 7c4d2d38f73..8ee2386b44d 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1,9 +1,11 @@ use futures03::{future::BoxFuture, stream::FuturesUnordered}; +use graph::abi; +use graph::abi::DynSolValueExt; +use graph::abi::FunctionExt; use graph::blockchain::client::ChainClient; use graph::blockchain::BlockHash; use graph::blockchain::ChainIdentifier; use graph::blockchain::ExtendedBlockPtr; - use graph::components::transaction_receipt::LightTransactionReceipt; use graph::data::store::ethereum::call; use graph::data::store::scalar; @@ -17,8 +19,6 @@ use graph::futures03::future::try_join_all; use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; -use graph::prelude::ethabi::ParamType; -use graph::prelude::ethabi::Token; use graph::prelude::tokio::try_join; use graph::prelude::web3::types::U256; use graph::slog::o; @@ -28,8 +28,7 @@ use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ anyhow::{self, anyhow, bail, ensure, Context}, - async_trait, debug, error, ethabi, hex, info, retry, serde_json as json, tiny_keccak, - trace, warn, + async_trait, debug, error, hex, info, retry, serde_json as json, tiny_keccak, trace, warn, web3::{ self, types::{ @@ -655,9 +654,10 @@ impl EthereumAdapter { match bytes.len() >= 4 && &bytes[..4] == solidity_revert_function_selector { false => None, - true => ethabi::decode(&[ParamType::String], &bytes[4..]) + true => abi::DynSolType::String + .abi_decode(&bytes[4..]) .ok() - .and_then(|tokens| tokens[0].clone().into_string()), + .and_then(|val| val.clone().as_str().map(ToOwned::to_owned)), } }; @@ -1541,7 +1541,7 @@ impl EthereumAdapterTrait for EthereumAdapter { logger: &Logger, inp_call: &ContractCall, cache: Arc, - ) -> Result<(Option>, call::Source), ContractCallError> { + ) -> Result<(Option>, call::Source), ContractCallError> { let mut result = self.contract_calls(logger, &[inp_call], cache).await?; // unwrap: self.contract_calls returns as many results as there were calls Ok(result.pop().unwrap()) @@ -1552,20 +1552,26 @@ impl EthereumAdapterTrait for EthereumAdapter { logger: &Logger, calls: &[&ContractCall], cache: Arc, - ) -> Result>, call::Source)>, ContractCallError> { + ) -> Result>, call::Source)>, ContractCallError> { fn as_req( logger: &Logger, call: &ContractCall, index: u32, ) -> Result { // Emit custom error for type mismatches. - for (token, kind) in call + for (val, kind) in call .args .iter() - .zip(call.function.inputs.iter().map(|p| &p.kind)) + .zip(call.function.inputs.iter().map(|p| p.selector_type())) { - if !token.type_check(kind) { - return Err(ContractCallError::TypeError(token.clone(), kind.clone())); + let kind: abi::DynSolType = kind.parse().map_err(|err| { + ContractCallError::ABIError(anyhow!( + "failed to parse function input type '{kind}': {err}" + )) + })?; + + if !val.type_check(&kind) { + return Err(ContractCallError::TypeError(val.clone(), kind.clone())); } } @@ -1573,8 +1579,8 @@ impl EthereumAdapterTrait for EthereumAdapter { let req = { let encoded_call = call .function - .encode_input(&call.args) - .map_err(ContractCallError::EncodingError)?; + .abi_encode_input(&call.args) + .map_err(|err| ContractCallError::EncodingError(err.into()))?; call::Request::new(call.address, encoded_call, index) }; @@ -1592,7 +1598,7 @@ impl EthereumAdapterTrait for EthereumAdapter { logger: &Logger, resp: call::Response, call: &ContractCall, - ) -> (Option>, call::Source) { + ) -> (Option>, call::Source) { let call::Response { retval, source, @@ -1600,7 +1606,7 @@ impl EthereumAdapterTrait for EthereumAdapter { } = resp; use call::Retval::*; match retval { - Value(output) => match call.function.decode_output(&output) { + Value(output) => match call.function.abi_decode_output(&output) { Ok(tokens) => (Some(tokens), source), Err(e) => { // Decode failures are reverts. The reasoning is that if Solidity fails to @@ -2655,9 +2661,9 @@ mod tests { EthereumBlockWithCalls, }; use graph::blockchain::BlockPtr; - use graph::prelude::ethabi::ethereum_types::U64; use graph::prelude::tokio::{self}; use graph::prelude::web3::transports::test::TestTransport; + use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Block, Bytes, H256}; use graph::prelude::web3::Web3; use graph::prelude::EthereumCall; diff --git a/chain/ethereum/src/ingestor.rs b/chain/ethereum/src/ingestor.rs index 935cb525936..a29aa8d17bd 100644 --- a/chain/ethereum/src/ingestor.rs +++ b/chain/ethereum/src/ingestor.rs @@ -9,8 +9,8 @@ use graph::{ blockchain::{BlockHash, BlockIngestor, BlockPtr, IngestorError}, cheap_clone::CheapClone, prelude::{ - async_trait, error, ethabi::ethereum_types::H256, info, tokio, trace, warn, ChainStore, - Error, EthereumBlockWithCalls, LogCode, Logger, + async_trait, error, info, tokio, trace, warn, web3::types::H256, ChainStore, Error, + EthereumBlockWithCalls, LogCode, Logger, }, }; use std::{sync::Arc, time::Duration}; diff --git a/chain/ethereum/src/runtime/abi.rs b/chain/ethereum/src/runtime/abi.rs index 1a4af0663cb..7af6470bf40 100644 --- a/chain/ethereum/src/runtime/abi.rs +++ b/chain/ethereum/src/runtime/abi.rs @@ -2,9 +2,9 @@ use super::runtime_adapter::UnresolvedContractCall; use crate::trigger::{ EthereumBlockData, EthereumCallData, EthereumEventData, EthereumTransactionData, }; +use graph::abi; use graph::{ prelude::{ - ethabi, web3::types::{Log, TransactionReceipt, H256}, BigInt, }, @@ -37,7 +37,7 @@ impl AscType for AscLogParamArray { } } -impl ToAscObj for &[ethabi::LogParam] { +impl ToAscObj for &[abi::DynSolParam] { fn to_asc_obj( &self, heap: &mut H, @@ -778,7 +778,7 @@ impl<'a> ToAscObj for ethabi::LogParam { +impl ToAscObj for abi::DynSolParam { fn to_asc_obj( &self, heap: &mut H, diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index 951958d786b..91f7e2dd1a4 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -7,6 +7,8 @@ use crate::{ }; use anyhow::{anyhow, Context, Error}; use blockchain::HostFn; +use graph::abi; +use graph::abi::DynSolValueExt; use graph::blockchain::ChainIdentifier; use graph::components::subgraph::HostMetrics; use graph::data::store::ethereum::call; @@ -14,6 +16,7 @@ use graph::data::store::scalar::BigInt; use graph::data::subgraph::API_VERSION_0_0_9; use graph::data_source; use graph::data_source::common::{ContractCall, MappingABI}; +use graph::prelude::web3::types::Address; use graph::prelude::web3::types::H160; use graph::runtime::gas::Gas; use graph::runtime::{AscIndexId, IndexForAscTypeId}; @@ -21,10 +24,7 @@ use graph::slog::debug; use graph::{ blockchain::{self, BlockPtr, HostFnCtx}, cheap_clone::CheapClone, - prelude::{ - ethabi::{self, Address, Token}, - EthereumCallCache, - }, + prelude::EthereumCallCache, runtime::{asc_get, asc_new, AscPtr, HostExportError}, semver::Version, slog::Logger, @@ -283,20 +283,7 @@ fn eth_call( abis: &[Arc], eth_call_gas: Option, metrics: Arc, -) -> Result>, HostExportError> { - // Helpers to log the result of the call at the end - fn tokens_as_string(tokens: &[Token]) -> String { - tokens.iter().map(|arg| arg.to_string()).join(", ") - } - - fn result_as_string(result: &Result>, HostExportError>) -> String { - match result { - Ok(Some(tokens)) => format!("({})", tokens_as_string(&tokens)), - Ok(None) => "none".to_string(), - Err(_) => "error".to_string(), - } - } - +) -> Result>, HostExportError> { let start_time = Instant::now(); // Obtain the path to the contract ABI @@ -375,16 +362,26 @@ fn eth_call( ); } - debug!(logger, "Contract call finished"; - "address" => format!("0x{:x}", &unresolved_call.contract_address), - "contract" => &unresolved_call.contract_name, - "signature" => &unresolved_call.function_signature, - "args" => format!("[{}]", tokens_as_string(&unresolved_call.function_args)), - "time_ms" => format!("{}ms", elapsed.as_millis()), - "result" => result_as_string(&result), - "block_hash" => block_ptr.hash_hex(), - "block_number" => block_ptr.block_number(), - "source" => source.to_string()); + let args_as_string = format!("[{}]", values_to_string(&unresolved_call.function_args)); + + let result_as_string = match &result { + Ok(Some(values)) => format!("({})", values_to_string(values)), + Ok(None) => "none".to_owned(), + Err(_err) => "error".to_owned(), + }; + + debug!( + logger, "Contract call finished"; + "address" => format!("0x{:x}", &unresolved_call.contract_address), + "contract" => &unresolved_call.contract_name, + "signature" => &unresolved_call.function_signature, + "args" => args_as_string, + "time_ms" => format!("{}ms", elapsed.as_millis()), + "result" => result_as_string, + "block_hash" => block_ptr.hash_hex(), + "block_number" => block_ptr.block_number(), + "source" => source.to_string(), + ); result } @@ -395,9 +392,18 @@ pub struct UnresolvedContractCall { pub contract_address: Address, pub function_name: String, pub function_signature: Option, - pub function_args: Vec, + pub function_args: Vec, } impl AscIndexId for AscUnresolvedContractCall { const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::SmartContractCall; } + +#[inline] +fn values_to_string(values: &[abi::DynSolValue]) -> String { + values + .iter() + .map(|x| x.to_string()) + .collect_vec() + .join(", ") +} diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index fa59438f244..9cce05e38c1 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -1,20 +1,20 @@ +use graph::abi; use graph::blockchain::MappingTriggerTrait; use graph::blockchain::TriggerData; use graph::data::subgraph::API_VERSION_0_0_2; use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; -use graph::prelude::ethabi::ethereum_types::H160; -use graph::prelude::ethabi::ethereum_types::H256; -use graph::prelude::ethabi::ethereum_types::U128; -use graph::prelude::ethabi::ethereum_types::U256; -use graph::prelude::ethabi::ethereum_types::U64; -use graph::prelude::ethabi::Address; -use graph::prelude::ethabi::LogParam; +use graph::prelude::web3::types::Address; use graph::prelude::web3::types::Block; use graph::prelude::web3::types::Log; use graph::prelude::web3::types::Transaction; use graph::prelude::web3::types::TransactionReceipt; +use graph::prelude::web3::types::H160; +use graph::prelude::web3::types::H256; +use graph::prelude::web3::types::U128; +use graph::prelude::web3::types::U256; +use graph::prelude::web3::types::U64; use graph::prelude::BlockNumber; use graph::prelude::BlockPtr; use graph::prelude::{CheapClone, EthereumCall}; @@ -47,7 +47,7 @@ pub enum MappingTrigger { block: Arc, transaction: Arc, log: Arc, - params: Vec, + params: Vec, receipt: Option>, calls: Vec, }, @@ -55,8 +55,8 @@ pub enum MappingTrigger { block: Arc, transaction: Arc, call: Arc, - inputs: Vec, - outputs: Vec, + inputs: Vec, + outputs: Vec, }, Block { block: Arc, @@ -64,7 +64,7 @@ pub enum MappingTrigger { } impl MappingTriggerTrait for MappingTrigger { - fn error_context(&self) -> std::string::String { + fn error_context(&self) -> String { let transaction_id = match self { MappingTrigger::Log { log, .. } => log.transaction_hash, MappingTrigger::Call { call, .. } => call.transaction_hash, @@ -86,13 +86,13 @@ impl std::fmt::Debug for MappingTrigger { Log { _transaction: Arc, _log: Arc, - _params: Vec, + _params: Vec, }, Call { _transaction: Arc, _call: Arc, - _inputs: Vec, - _outputs: Vec, + _inputs: Vec, + _outputs: Vec, }, Block, } @@ -544,7 +544,7 @@ impl<'a> EthereumTransactionData<'a> { pub struct EthereumEventData<'a> { pub block: EthereumBlockData<'a>, pub transaction: EthereumTransactionData<'a>, - pub params: &'a [LogParam], + pub params: &'a [abi::DynSolParam], log: &'a Log, } @@ -553,7 +553,7 @@ impl<'a> EthereumEventData<'a> { block: &'a Block, tx: &'a Transaction, log: &'a Log, - params: &'a [LogParam], + params: &'a [abi::DynSolParam], ) -> Self { EthereumEventData { block: EthereumBlockData::from(block), @@ -591,8 +591,8 @@ impl<'a> EthereumEventData<'a> { pub struct EthereumCallData<'a> { pub block: EthereumBlockData<'a>, pub transaction: EthereumTransactionData<'a>, - pub inputs: &'a [LogParam], - pub outputs: &'a [LogParam], + pub inputs: &'a [abi::DynSolParam], + pub outputs: &'a [abi::DynSolParam], call: &'a EthereumCall, } @@ -601,8 +601,8 @@ impl<'a> EthereumCallData<'a> { block: &'a Block, transaction: &'a Transaction, call: &'a EthereumCall, - inputs: &'a [LogParam], - outputs: &'a [LogParam], + inputs: &'a [abi::DynSolParam], + outputs: &'a [abi::DynSolParam], ) -> EthereumCallData<'a> { EthereumCallData { block: EthereumBlockData::from(block), diff --git a/graph/Cargo.toml b/graph/Cargo.toml index bb4287b2c31..9c85c1a9709 100644 --- a/graph/Cargo.toml +++ b/graph/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +alloy = { workspace = true } base64 = "=0.21.7" anyhow = "1.0" async-trait = "0.1.74" diff --git a/graph/src/abi/event_ext.rs b/graph/src/abi/event_ext.rs new file mode 100644 index 00000000000..ac03a778bef --- /dev/null +++ b/graph/src/abi/event_ext.rs @@ -0,0 +1,181 @@ +use std::collections::VecDeque; + +use alloy::json_abi::Event; +use alloy::primitives::LogData; +use anyhow::anyhow; +use anyhow::Context; +use anyhow::Result; +use itertools::Itertools; +use web3::types::Log; + +use crate::abi::{DynSolParam, DynSolValue}; + +pub trait EventExt { + fn decode_log(&self, log: &Log) -> Result>; +} + +impl EventExt for Event { + fn decode_log(&self, log: &Log) -> Result> { + let log_data = log_to_log_data(log)?; + let decoded_event = alloy::dyn_abi::EventExt::decode_log(self, &log_data, true)?; + let mut indexed: VecDeque = decoded_event.indexed.into(); + let mut body: VecDeque = decoded_event.body.into(); + + if self.inputs.len() != indexed.len() + body.len() { + return Err(anyhow!( + "unexpected number of decoded event inputs; expected {}, got {}", + self.inputs.len(), + indexed.len() + body.len(), + )); + } + + let mut decoded_params = Vec::with_capacity(self.inputs.len()); + + for input in &self.inputs { + decoded_params.push(DynSolParam { + name: input.name.clone(), + value: { + if input.indexed { + indexed.pop_front().unwrap() + } else { + body.pop_front().unwrap() + } + }, + }); + } + + Ok(decoded_params) + } +} + +fn log_to_log_data(log: &Log) -> Result { + let topics = log + .topics + .iter() + .map(|x| x.to_fixed_bytes().into()) + .collect_vec(); + + let data = log.data.0.clone().into(); + + LogData::new(topics, data).context("log has an invalid number of topics") +} + +#[cfg(test)] +mod tests { + use alloy::dyn_abi::DynSolValue; + use alloy::primitives::U256; + + use super::*; + + fn make_log(topics: &[[u8; 32]], data: Vec) -> Log { + Log { + address: [1; 20].into(), + topics: topics.iter().map(Into::into).collect(), + data: data.into(), + block_hash: None, + block_number: None, + transaction_hash: None, + transaction_index: None, + log_index: None, + transaction_log_index: None, + log_type: None, + removed: None, + } + } + + #[test] + fn decode_log_no_topic_0() { + let event = Event::parse("event X(uint256 indexed a, bytes32 b)").unwrap(); + let a = U256::from(10).to_be_bytes::<32>(); + let b = DynSolValue::FixedBytes([10; 32].into(), 32).abi_encode(); + + let log = make_log(&[a], b); + let err = event.decode_log(&log).unwrap_err(); + + assert_eq!( + err.to_string(), + "invalid log topic list length: expected 2 topics, got 1", + ); + } + + #[test] + fn decode_log_invalid_topic_0() { + let event = Event::parse("event X(uint256 indexed a, bytes32 b)").unwrap(); + let a = U256::from(10).to_be_bytes::<32>(); + let b = DynSolValue::FixedBytes([10; 32].into(), 32).abi_encode(); + + let log = make_log(&[[0; 32], a], b); + let err = event.decode_log(&log).unwrap_err(); + + assert!(err.to_string().starts_with("invalid event signature:")); + } + + #[test] + fn decode_log_success() { + let event = Event::parse("event X(uint256 indexed a, bytes32 b)").unwrap(); + let topic_0 = event.selector().0; + let a = U256::from(10).to_be_bytes::<32>(); + let b = DynSolValue::FixedBytes([10; 32].into(), 32).abi_encode(); + + let log = make_log(&[topic_0, a], b); + let resp = event.decode_log(&log).unwrap(); + + assert_eq!( + resp, + vec![ + DynSolParam { + name: "a".to_owned(), + value: DynSolValue::Uint(U256::from(10), 256), + }, + DynSolParam { + name: "b".to_owned(), + value: DynSolValue::FixedBytes([10; 32].into(), 32), + } + ], + ); + } + + #[test] + fn decode_log_too_many_topics() { + let event = Event::parse("event X(uint256 indexed a, bytes32 b)").unwrap(); + let topic_0 = event.selector().0; + let a = U256::from(10).to_be_bytes::<32>(); + let b = DynSolValue::FixedBytes([10; 32].into(), 32).abi_encode(); + + let log = make_log(&[topic_0, a, a, a, a], b); + let err = event.decode_log(&log).unwrap_err(); + + assert_eq!(err.to_string(), "log has an invalid number of topics"); + } + + #[test] + fn decode_log_when_indexed_param_is_not_the_first() { + let event = Event::parse("event X(uint256 a, uint256 indexed b, bytes32 c)").unwrap(); + let topic_0 = event.selector().0; + let a = DynSolValue::Uint(U256::from(10), 32); + let b = U256::from(20).to_be_bytes::<32>(); + let c = DynSolValue::FixedBytes([30; 32].into(), 32); + let data = DynSolValue::Tuple(vec![a, c]).abi_encode(); + + let log = make_log(&[topic_0, b], data); + let resp = event.decode_log(&log).unwrap(); + + assert_eq!( + resp, + vec![ + DynSolParam { + name: "a".to_owned(), + value: DynSolValue::Uint(U256::from(10), 256), + }, + DynSolParam { + name: "b".to_owned(), + value: DynSolValue::Uint(U256::from(20), 256), + }, + DynSolParam { + name: "c".to_owned(), + value: DynSolValue::FixedBytes([30; 32].into(), 32), + } + ], + ); + } +} diff --git a/graph/src/abi/function_ext.rs b/graph/src/abi/function_ext.rs new file mode 100644 index 00000000000..634ca9a08d6 --- /dev/null +++ b/graph/src/abi/function_ext.rs @@ -0,0 +1,303 @@ +use std::borrow::Cow; + +use alloy::dyn_abi::DynSolType; +use alloy::dyn_abi::DynSolValue; +use alloy::dyn_abi::Specifier; +use alloy::json_abi::Function; +use alloy::json_abi::Param; +use anyhow::anyhow; +use anyhow::Result; +use itertools::Itertools; + +use crate::abi::DynSolValueExt; + +pub trait FunctionExt { + /// Returns the signature of this function in the following formats: + /// - if the function has no outputs: `$name($($inputs),*)` + /// - if the function has outputs: `$name($($inputs),*):($(outputs),*)` + /// + /// Examples: + /// - `functionName()` + /// - `functionName():(uint256)` + /// - `functionName(bool):(uint256,string)` + /// - `functionName(uint256,bytes32):(string,uint256)` + fn signature_compat(&self) -> String; + + /// ABI-decodes the given data according to the function's input types. + fn abi_decode_input(&self, data: &[u8]) -> Result>; + + /// ABI-decodes the given data according to the function's output types. + fn abi_decode_output(&self, data: &[u8]) -> Result>; + + /// ABI-encodes the given values, prefixed by the function's selector, if any. + /// + /// This behaviour is to ensure consistency with `ethabi`. + fn abi_encode_input(&self, values: &[DynSolValue]) -> Result>; +} + +impl FunctionExt for Function { + fn signature_compat(&self) -> String { + let name = &self.name; + let inputs = &self.inputs; + let outputs = &self.outputs; + + // This is what `alloy` uses internally when creating signatures. + const MAX_SOL_TYPE_LEN: usize = 32; + + let mut sig_cap = name.len() + 1 + inputs.len() * MAX_SOL_TYPE_LEN + 1; + + if !outputs.is_empty() { + sig_cap = sig_cap + 2 + outputs.len() * MAX_SOL_TYPE_LEN + 1; + } + + let mut sig = String::with_capacity(sig_cap); + + sig.push_str(&name); + signature_part(&inputs, &mut sig); + + if !outputs.is_empty() { + sig.push(':'); + signature_part(&outputs, &mut sig); + } + + sig + } + + fn abi_decode_input(&self, data: &[u8]) -> Result> { + (self as &dyn alloy::dyn_abi::FunctionExt) + .abi_decode_input(data, true) + .map_err(Into::into) + } + + fn abi_decode_output(&self, data: &[u8]) -> Result> { + (self as &dyn alloy::dyn_abi::FunctionExt) + .abi_decode_output(data, true) + .map_err(Into::into) + } + + fn abi_encode_input(&self, values: &[DynSolValue]) -> Result> { + let inputs = &self.inputs; + + if inputs.len() != values.len() { + return Err(anyhow!( + "unexpected number of values; expected {}, got {}", + inputs.len(), + values.len(), + )); + } + + let mut fixed_values = Vec::with_capacity(values.len()); + + for (i, input) in inputs.iter().enumerate() { + let ty = input.resolve()?; + let val = &values[i]; + + fixed_values.push(fix_type_size(&ty, val)?); + } + + if fixed_values.iter().all(|x| matches!(x, Cow::Borrowed(_))) { + return (self as &dyn alloy::dyn_abi::JsonAbiExt) + .abi_encode_input(values) + .map_err(Into::into); + } + + // Required because of `alloy::dyn_abi::JsonAbiExt::abi_encode_input` API; + let owned_fixed_values = fixed_values + .into_iter() + .map(|x| x.into_owned()) + .collect_vec(); + + (self as &dyn alloy::dyn_abi::JsonAbiExt) + .abi_encode_input(&owned_fixed_values) + .map_err(Into::into) + } +} + +// An efficient way to compute a part of the signature without new allocations. +fn signature_part(params: &[Param], out: &mut String) { + out.push('('); + + match params.len() { + 0 => {} + 1 => { + params[0].selector_type_raw(out); + } + n => { + params[0].selector_type_raw(out); + + for i in 1..n { + out.push(','); + params[i].selector_type_raw(out); + } + } + } + + out.push(')'); +} + +// Alloy is stricter in type checking than `ehtabi` and requires that the decoded values have +// exactly the same number of bits / bytes as the type used for checking. +// +// This is a problem because in some ASC conversions we lose the original number of bits / bytes +// if the actual data takes less memory. +// +// This method fixes that in a simple but not very cheap way, by encoding the value and trying +// to decode it again using the given type. The result fixes the number of bits / bytes in the +// decoded values, so we can use `alloy` methods that have strict type checking internally. +fn fix_type_size<'a>(ty: &DynSolType, val: &'a DynSolValue) -> Result> { + if val.matches(ty) { + return Ok(Cow::Borrowed(val)); + } + + if !val.type_check(ty) { + return Err(anyhow!( + "invalid value type; expected '{}', got '{:?}'", + ty.sol_type_name(), + val.sol_type_name(), + )); + } + + let bytes = val.abi_encode(); + let new_val = ty.abi_decode(&bytes)?; + + Ok(Cow::Owned(new_val)) +} + +#[cfg(test)] +mod tests { + use alloy::primitives::I256; + use alloy::primitives::U256; + + use super::*; + + fn s(f: &str) -> String { + Function::parse(f).unwrap().signature_compat() + } + + fn u256(u: u64) -> U256 { + U256::from(u) + } + + fn i256(i: i32) -> I256 { + I256::try_from(i).unwrap() + } + + #[test] + fn signature_compat_no_inputs_no_outputs() { + assert_eq!(s("x()"), "x()"); + } + + #[test] + fn signature_compat_one_input_no_outputs() { + assert_eq!(s("x(uint256 a)"), "x(uint256)"); + } + + #[test] + fn signature_compat_multiple_inputs_no_outputs() { + assert_eq!(s("x(uint256 a, bytes32 b)"), "x(uint256,bytes32)"); + } + + #[test] + fn signature_compat_no_inputs_one_output() { + assert_eq!(s("x() returns (uint256)"), "x():(uint256)"); + } + + #[test] + fn signature_compat_no_inputs_multiple_outputs() { + assert_eq!(s("x() returns (uint256, bytes32)"), "x():(uint256,bytes32)"); + } + + #[test] + fn signature_compat_multiple_inputs_multiple_outputs() { + assert_eq!( + s("x(bytes32 a, uint256 b) returns (uint256, bytes32)"), + "x(bytes32,uint256):(uint256,bytes32)", + ); + } + + #[test] + fn abi_decode_input() { + use DynSolValue::{Int, Tuple, Uint}; + + let f = Function::parse("x(uint256 a, int256 b)").unwrap(); + let data = Tuple(vec![Uint(u256(10), 256), Int(i256(-10), 256)]).abi_encode_params(); + let inputs = f.abi_decode_input(&data).unwrap(); + + assert_eq!(inputs, vec![Uint(u256(10), 256), Int(i256(-10), 256)]); + } + + #[test] + fn abi_decode_output() { + use DynSolValue::{Int, Tuple, Uint}; + + let f = Function::parse("x() returns (uint256 a, int256 b)").unwrap(); + let data = Tuple(vec![Uint(u256(10), 256), Int(i256(-10), 256)]).abi_encode_params(); + let outputs = f.abi_decode_output(&data).unwrap(); + + assert_eq!(outputs, vec![Uint(u256(10), 256), Int(i256(-10), 256)]); + } + + #[test] + fn abi_encode_input_no_values() { + let f = Function::parse("x(uint256 a, int256 b)").unwrap(); + let err = f.abi_encode_input(&[]).unwrap_err(); + + assert_eq!( + err.to_string(), + "unexpected number of values; expected 2, got 0", + ); + } + + #[test] + fn abi_encode_input_too_many_values() { + use DynSolValue::Bool; + + let f = Function::parse("x(uint256 a, int256 b)").unwrap(); + + let err = f + .abi_encode_input(&[Bool(true), Bool(false), Bool(true)]) + .unwrap_err(); + + assert_eq!( + err.to_string(), + "unexpected number of values; expected 2, got 3", + ); + } + + #[test] + fn abi_encode_input_invalid_types() { + use DynSolValue::Bool; + + let f = Function::parse("x(uint256 a, int256 b)").unwrap(); + let err = f.abi_encode_input(&[Bool(true), Bool(false)]).unwrap_err(); + assert!(err.to_string().starts_with("invalid value type;")); + } + + #[test] + fn abi_encode_success() { + use DynSolValue::{Bool, Uint}; + + let f = Function::parse("x(uint256 a, bool b)").unwrap(); + let a = Uint(u256(10), 256); + let b = Bool(true); + + let data = f.abi_encode_input(&[a.clone(), b.clone()]).unwrap(); + let inputs = f.abi_decode_input(&data[4..]).unwrap(); + + assert_eq!(inputs, vec![a, b]); + } + + #[test] + fn abi_encode_success_with_size_fix() { + use DynSolValue::{Int, Uint}; + + let f = Function::parse("x(uint256 a, int256 b)").unwrap(); + let a = Uint(u256(10), 32); + let b = Int(i256(-10), 32); + + let data = f.abi_encode_input(&[a, b]).unwrap(); + let inputs = f.abi_decode_input(&data[4..]).unwrap(); + + assert_eq!(inputs, vec![Uint(u256(10), 256), Int(i256(-10), 256)]); + } +} diff --git a/graph/src/abi/mod.rs b/graph/src/abi/mod.rs new file mode 100644 index 00000000000..88fe14b1806 --- /dev/null +++ b/graph/src/abi/mod.rs @@ -0,0 +1,20 @@ +mod event_ext; +mod function_ext; +mod param; +mod value_ext; + +pub use alloy::dyn_abi::DynSolType; +pub use alloy::dyn_abi::DynSolValue; + +pub use alloy::json_abi::Event; +pub use alloy::json_abi::Function; +pub use alloy::json_abi::JsonAbi; +pub use alloy::json_abi::StateMutability; + +pub use alloy::primitives::I256; +pub use alloy::primitives::U256; + +pub use self::event_ext::EventExt; +pub use self::function_ext::FunctionExt; +pub use self::param::DynSolParam; +pub use self::value_ext::DynSolValueExt; diff --git a/graph/src/abi/param.rs b/graph/src/abi/param.rs new file mode 100644 index 00000000000..49e0f0878ea --- /dev/null +++ b/graph/src/abi/param.rs @@ -0,0 +1,7 @@ +use alloy::dyn_abi::DynSolValue; + +#[derive(Clone, Debug, PartialEq)] +pub struct DynSolParam { + pub name: String, + pub value: DynSolValue, +} diff --git a/graph/src/abi/value_ext.rs b/graph/src/abi/value_ext.rs new file mode 100644 index 00000000000..cb0f220e036 --- /dev/null +++ b/graph/src/abi/value_ext.rs @@ -0,0 +1,277 @@ +use alloy::dyn_abi::DynSolType; +use alloy::dyn_abi::DynSolValue; +use anyhow::anyhow; +use anyhow::Result; +use itertools::Itertools; + +pub trait DynSolValueExt { + /// Creates a fixed-byte decoded value from a slice. + /// + /// Fails if the source slice exceeds 32 bytes. + fn fixed_bytes_from_slice(s: &[u8]) -> Result; + + /// Returns the decoded value as a string. + /// + /// The resulting string contains no type information. + fn to_string(&self) -> String; + + /// Checks whether the value is of the specified type. + /// + /// For types with additional size information, returns true if the size of the value is less + /// than or equal to the size of the specified type. + #[must_use] + fn type_check(&self, ty: &DynSolType) -> bool; +} + +impl DynSolValueExt for DynSolValue { + fn fixed_bytes_from_slice(s: &[u8]) -> Result { + let num_bytes = s.len(); + + if num_bytes > 32 { + return Err(anyhow!( + "input slice must contain a maximum of 32 bytes, got {num_bytes}" + )); + } + + let mut bytes = [0u8; 32]; + + // Access: If `x` is of type `bytesI`, then `x[k]` for `0 <= k < I` returns the `k`th byte. + // Ref: + bytes[..num_bytes].copy_from_slice(s); + + Ok(Self::FixedBytes(bytes.into(), num_bytes)) + } + + fn to_string(&self) -> String { + let s = |v: &[Self]| v.iter().map(|x| x.to_string()).collect_vec().join(","); + + // Output format is taken from `ethabi`; + // See: + match self { + Self::Bool(v) => v.to_string(), + Self::Int(v, _) => format!("{v:x}"), + Self::Uint(v, _) => format!("{v:x}"), + Self::FixedBytes(v, _) => hex::encode(v), + Self::Address(v) => format!("{v:x}"), + Self::Function(v) => format!("{v:x}"), + Self::Bytes(v) => hex::encode(v), + Self::String(v) => v.to_owned(), + Self::Array(v) => format!("[{}]", s(v)), + Self::FixedArray(v) => format!("[{}]", s(v)), + Self::Tuple(v) => format!("({})", s(v)), + } + } + + fn type_check(&self, ty: &DynSolType) -> bool { + match self { + Self::Bool(_) => *ty == DynSolType::Bool, + Self::Int(_, a) => { + if let DynSolType::Int(b) = ty { + b >= a + } else { + false + } + } + Self::Uint(_, a) => { + if let DynSolType::Uint(b) = ty { + b >= a + } else { + false + } + } + Self::FixedBytes(_, a) => { + if let DynSolType::FixedBytes(b) = ty { + b >= a + } else { + false + } + } + Self::Address(_) => *ty == DynSolType::Address, + Self::Function(_) => *ty == DynSolType::Function, + Self::Bytes(_) => *ty == DynSolType::Bytes, + Self::String(_) => *ty == DynSolType::String, + Self::Array(values) => { + if let DynSolType::Array(ty) = ty { + values.iter().all(|x| x.type_check(ty)) + } else { + false + } + } + Self::FixedArray(values) => { + if let DynSolType::FixedArray(ty, size) = ty { + *size == values.len() && values.iter().all(|x| x.type_check(ty)) + } else { + false + } + } + Self::Tuple(values) => { + if let DynSolType::Tuple(types) = ty { + types.len() == values.len() + && values + .iter() + .enumerate() + .all(|(i, x)| x.type_check(&types[i])) + } else { + false + } + } + } + } +} + +#[cfg(test)] +mod tests { + use alloy::primitives::I256; + use alloy::primitives::U256; + + use super::*; + + #[test] + fn fixed_bytes_from_slice_empty_slice() { + let val = DynSolValue::fixed_bytes_from_slice(&[]).unwrap(); + let bytes = [0; 32]; + + assert_eq!(val, DynSolValue::FixedBytes(bytes.into(), 0)); + } + + #[test] + fn fixed_bytes_from_slice_one_byte() { + let val = DynSolValue::fixed_bytes_from_slice(&[10]).unwrap(); + let mut bytes = [0; 32]; + bytes[0] = 10; + + assert_eq!(val, DynSolValue::FixedBytes(bytes.into(), 1)); + } + + #[test] + fn fixed_bytes_from_slice_multiple_bytes() { + let val = DynSolValue::fixed_bytes_from_slice(&[10, 20, 30]).unwrap(); + let mut bytes = [0; 32]; + bytes[0] = 10; + bytes[1] = 20; + bytes[2] = 30; + + assert_eq!(val, DynSolValue::FixedBytes(bytes.into(), 3)); + } + + #[test] + fn fixed_bytes_from_slice_max_bytes() { + let val = DynSolValue::fixed_bytes_from_slice(&[10; 32]).unwrap(); + let bytes = [10; 32]; + + assert_eq!(val, DynSolValue::FixedBytes(bytes.into(), 32)); + } + + #[test] + fn fixed_bytes_from_slice_too_many_bytes() { + DynSolValue::fixed_bytes_from_slice(&[10; 33]).unwrap_err(); + } + + #[test] + fn to_string() { + use DynSolValue::*; + + assert_eq!(Bool(false).to_string(), "false"); + assert_eq!(Bool(true).to_string(), "true"); + + assert_eq!( + Int(I256::try_from(-10).unwrap(), 256).to_string(), + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6", + ); + + assert_eq!(Uint(U256::from(10), 256).to_string(), "a"); + + assert_eq!( + FixedBytes([10; 32].into(), 32).to_string(), + "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + ); + + assert_eq!( + Address([10; 20].into()).to_string(), + "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + ); + + assert_eq!( + Function([10; 24].into()).to_string(), + "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + ); + + assert_eq!(Bytes(vec![10, 20, 30]).to_string(), "0a141e"); + + assert_eq!( + String("one two three".to_owned()).to_string(), + "one two three" + ); + + assert_eq!( + Array(vec![String("one".to_owned()), String("two".to_owned())]).to_string(), + "[one,two]", + ); + + assert_eq!( + FixedArray(vec![String("one".to_owned()), String("two".to_owned())]).to_string(), + "[one,two]" + ); + + assert_eq!( + Tuple(vec![String("one".to_owned()), String("two".to_owned())]).to_string(), + "(one,two)" + ); + } + + #[test] + fn type_check() { + use DynSolType as T; + use DynSolValue::*; + + assert!(Bool(true).type_check(&T::Bool)); + assert!(!Bool(true).type_check(&T::Int(256))); + + assert!(!Int(I256::try_from(-10).unwrap(), 32).type_check(&T::Int(24))); + assert!(Int(I256::try_from(-10).unwrap(), 32).type_check(&T::Int(32))); + assert!(Int(I256::try_from(-10).unwrap(), 32).type_check(&T::Int(256))); + assert!(!Int(I256::try_from(-10).unwrap(), 32).type_check(&T::Uint(256))); + + assert!(!Uint(U256::from(10), 32).type_check(&T::Uint(24))); + assert!(Uint(U256::from(10), 32).type_check(&T::Uint(32))); + assert!(Uint(U256::from(10), 32).type_check(&T::Uint(256))); + assert!(!Uint(U256::from(10), 32).type_check(&T::FixedBytes(32))); + + assert!(!FixedBytes([0; 32].into(), 16).type_check(&T::FixedBytes(8))); + assert!(FixedBytes([0; 32].into(), 16).type_check(&T::FixedBytes(16))); + assert!(FixedBytes([0; 32].into(), 16).type_check(&T::FixedBytes(32))); + assert!(!FixedBytes([0; 32].into(), 32).type_check(&T::Address)); + + assert!(Address([0; 20].into()).type_check(&T::Address)); + assert!(!Address([0; 20].into()).type_check(&T::Function)); + + assert!(Function([0; 24].into()).type_check(&T::Function)); + assert!(!Function([0; 24].into()).type_check(&T::Bytes)); + + assert!(Bytes(vec![0, 0, 0]).type_check(&T::Bytes)); + assert!(!Bytes(vec![0, 0, 0]).type_check(&T::String)); + + assert!(String("".to_owned()).type_check(&T::String)); + assert!(!String("".to_owned()).type_check(&T::Array(Box::new(T::Bool)))); + + assert!(Array(vec![Bool(true)]).type_check(&T::Array(Box::new(T::Bool)))); + assert!(!Array(vec![Bool(true)]).type_check(&T::Array(Box::new(T::String)))); + assert!(!Array(vec![Bool(true)]).type_check(&T::FixedArray(Box::new(T::Bool), 1))); + + assert!(!FixedArray(vec![String("".to_owned())]) + .type_check(&T::FixedArray(Box::new(T::Bool), 1))); + assert!(!FixedArray(vec![Bool(true), Bool(false)]) + .type_check(&T::FixedArray(Box::new(T::Bool), 1))); + assert!(FixedArray(vec![Bool(true), Bool(false)]) + .type_check(&T::FixedArray(Box::new(T::Bool), 2))); + assert!(!FixedArray(vec![Bool(true), Bool(false)]) + .type_check(&T::FixedArray(Box::new(T::Bool), 3))); + assert!(!FixedArray(vec![Bool(true), Bool(false)]) + .type_check(&T::Tuple(vec![T::Bool, T::Bool]))); + + assert!(!Tuple(vec![Bool(true), Bool(false)]).type_check(&T::Tuple(vec![T::Bool]))); + assert!(Tuple(vec![Bool(true), Bool(false)]).type_check(&T::Tuple(vec![T::Bool, T::Bool]))); + assert!(!Tuple(vec![Bool(true)]).type_check(&T::Tuple(vec![T::Bool, T::Bool]))); + assert!(!Tuple(vec![Bool(true)]).type_check(&T::Bool)); + } +} diff --git a/graph/src/cheap_clone.rs b/graph/src/cheap_clone.rs index b8863d3918e..0d894d84434 100644 --- a/graph/src/cheap_clone.rs +++ b/graph/src/cheap_clone.rs @@ -118,4 +118,4 @@ cheap_clone_is_copy!( &'static str, std::time::Duration ); -cheap_clone_is_copy!(ethabi::Address); +cheap_clone_is_copy!(web3::types::Address); diff --git a/graph/src/components/store/mod.rs b/graph/src/components/store/mod.rs index 585df5945f1..66a020ead21 100644 --- a/graph/src/components/store/mod.rs +++ b/graph/src/components/store/mod.rs @@ -1163,7 +1163,7 @@ pub struct CachedEthereumCall { pub block_ptr: BlockPtr, /// The address to the called contract. - pub contract_address: ethabi::Address, + pub contract_address: web3::types::Address, /// The encoded return value of this call. pub return_value: Vec, diff --git a/graph/src/data/store/ethereum.rs b/graph/src/data/store/ethereum.rs index 12d48f992df..ae39f1ffcbc 100644 --- a/graph/src/data/store/ethereum.rs +++ b/graph/src/data/store/ethereum.rs @@ -104,7 +104,7 @@ pub mod call { /// on the call's return value #[derive(Debug, Clone, CheapClone)] pub struct Request { - pub address: ethabi::Address, + pub address: web3::types::Address, pub encoded_call: Arc, /// The index is set by the caller and is used to identify the /// request in related data structures that the caller might have @@ -112,7 +112,7 @@ pub mod call { } impl Request { - pub fn new(address: ethabi::Address, encoded_call: Vec, index: u32) -> Self { + pub fn new(address: web3::types::Address, encoded_call: Vec, index: u32) -> Self { Request { address, encoded_call: Arc::new(Bytes::from(encoded_call)), diff --git a/graph/src/data_source/common.rs b/graph/src/data_source/common.rs index 57781815f5f..bd6eecfe05a 100644 --- a/graph/src/data_source/common.rs +++ b/graph/src/data_source/common.rs @@ -1,8 +1,10 @@ +use crate::abi; +use crate::abi::DynSolValueExt; +use crate::abi::FunctionExt; use crate::blockchain::block_stream::EntitySourceOperation; use crate::prelude::{BlockPtr, Value}; use crate::{components::link_resolver::LinkResolver, data::value::Word, prelude::Link}; use anyhow::{anyhow, Context, Error}; -use ethabi::{Address, Contract, Function, LogParam, ParamType, Token}; use graph_derive::CheapClone; use lazy_static::lazy_static; use num_bigint::Sign; @@ -11,12 +13,13 @@ use serde::de; use serde::Deserialize; use slog::Logger; use std::{str::FromStr, sync::Arc}; +use web3::types::Address; use web3::types::{Log, H160}; #[derive(Clone, Debug, PartialEq)] pub struct MappingABI { pub name: String, - pub contract: Contract, + pub contract: abi::JsonAbi, } impl MappingABI { @@ -25,24 +28,27 @@ impl MappingABI { contract_name: &str, name: &str, signature: Option<&str>, - ) -> Result<&Function, Error> { + ) -> Result<&abi::Function, Error> { let contract = &self.contract; let function = match signature { // Behavior for apiVersion < 0.0.4: look up function by name; for overloaded // functions this always picks the same overloaded variant, which is incorrect // and may lead to encoding/decoding errors - None => contract.function(name).with_context(|| { - format!( - "Unknown function \"{}::{}\" called from WASM runtime", - contract_name, name - ) - })?, + None => contract + .function(name) + .and_then(|matches| matches.first()) + .with_context(|| { + format!( + "Unknown function \"{}::{}\" called from WASM runtime", + contract_name, name + ) + })?, // Behavior for apiVersion >= 0.0.04: look up function by signature of // the form `functionName(uint256,string) returns (bytes32,string)`; this // correctly picks the correct variant of an overloaded function Some(ref signature) => contract - .functions_by_name(name) + .function(name) .with_context(|| { format!( "Unknown function \"{}::{}\" called from WASM runtime", @@ -50,7 +56,7 @@ impl MappingABI { ) })? .iter() - .find(|f| signature == &f.signature()) + .find(|f| signature == &f.signature_compat()) .with_context(|| { format!( "Unknown function \"{}::{}\" with signature `{}` \ @@ -81,7 +87,7 @@ impl UnresolvedMappingABI { self.name, self.file.link ) })?; - let contract = Contract::load(&*contract_bytes) + let contract = serde_json::from_slice(&*contract_bytes) .with_context(|| format!("failed to load ABI {}", self.name))?; Ok(MappingABI { name: self.name, @@ -123,21 +129,23 @@ impl CallDecl { self.expr.validate_args() } - pub fn address_for_log(&self, log: &Log, params: &[LogParam]) -> Result { + pub fn address_for_log(&self, log: &Log, params: &[abi::DynSolParam]) -> Result { let address = match &self.expr.address { CallArg::HexAddress(address) => *address, CallArg::Ethereum(arg) => match arg { EthereumArg::Address => log.address, EthereumArg::Param(name) => { - let value = params + let value = ¶ms .iter() .find(|param| ¶m.name == name.as_str()) - .ok_or_else(|| anyhow!("unknown param {name}"))? - .value - .clone(); - value - .into_address() - .ok_or_else(|| anyhow!("param {name} is not an address"))? + .ok_or_else(|| anyhow!("unknown param '{name}'"))? + .value; + + let address = value + .as_address() + .ok_or_else(|| anyhow!("param '{name}' is not an address"))?; + + Address::from(address.into_array()) } }, CallArg::Subgraph(_) => { @@ -149,14 +157,24 @@ impl CallDecl { Ok(address) } - pub fn args_for_log(&self, log: &Log, params: &[LogParam]) -> Result, Error> { + pub fn args_for_log( + &self, + log: &Log, + params: &[abi::DynSolParam], + ) -> Result, Error> { + use abi::DynSolValue; + self.expr .args .iter() .map(|arg| match arg { - CallArg::HexAddress(address) => Ok(Token::Address(*address)), + CallArg::HexAddress(address) => { + Ok(DynSolValue::Address(address.to_fixed_bytes().into())) + } CallArg::Ethereum(arg) => match arg { - EthereumArg::Address => Ok(Token::Address(log.address)), + EthereumArg::Address => { + Ok(DynSolValue::Address(log.address.to_fixed_bytes().into())) + } EthereumArg::Param(name) => { let value = params .iter() @@ -174,7 +192,10 @@ impl CallDecl { .collect() } - pub fn get_function(&self, mapping: &dyn FindMappingABI) -> Result { + pub fn get_function( + &self, + mapping: &dyn FindMappingABI, + ) -> Result { let contract_name = self.expr.abi.to_string(); let function_name = self.expr.func.as_str(); let abi = mapping.find_abi(&contract_name)?; @@ -185,6 +206,7 @@ impl CallDecl { // and may lead to encoding/decoding errors abi.contract .function(function_name) + .and_then(|matches| matches.first()) .cloned() .with_context(|| { format!( @@ -232,8 +254,8 @@ impl CallDecl { pub fn args_for_entity_handler( &self, entity: &EntitySourceOperation, - param_types: Vec, - ) -> Result, Error> { + param_types: Vec, + ) -> Result, Error> { self.validate_entity_handler_args(¶m_types)?; self.expr @@ -247,7 +269,7 @@ impl CallDecl { } /// Validates that the number of provided arguments matches the expected parameter types. - fn validate_entity_handler_args(&self, param_types: &[ParamType]) -> Result<(), Error> { + fn validate_entity_handler_args(&self, param_types: &[abi::DynSolType]) -> Result<(), Error> { if self.expr.args.len() != param_types.len() { return Err(anyhow!( "mismatched number of arguments: expected {}, got {}", @@ -263,9 +285,9 @@ impl CallDecl { fn process_entity_handler_arg( &self, arg: &CallArg, - expected_type: &ParamType, + expected_type: &abi::DynSolType, entity: &EntitySourceOperation, - ) -> Result { + ) -> Result { match arg { CallArg::HexAddress(address) => self.process_hex_address(*address, expected_type), CallArg::Ethereum(_) => Err(anyhow!( @@ -281,10 +303,12 @@ impl CallDecl { fn process_hex_address( &self, address: H160, - expected_type: &ParamType, - ) -> Result { + expected_type: &abi::DynSolType, + ) -> Result { match expected_type { - ParamType::Address => Ok(Token::Address(address)), + abi::DynSolType::Address => { + Ok(abi::DynSolValue::Address(address.to_fixed_bytes().into())) + } _ => Err(anyhow!( "type mismatch: hex address provided for non-address parameter" )), @@ -295,9 +319,9 @@ impl CallDecl { fn process_entity_param( &self, name: &str, - expected_type: &ParamType, + expected_type: &abi::DynSolType, entity: &EntitySourceOperation, - ) -> Result { + ) -> Result { let value = entity .entity .get(name) @@ -311,27 +335,43 @@ impl CallDecl { fn convert_entity_value_to_token( &self, value: &Value, - expected_type: &ParamType, + expected_type: &abi::DynSolType, param_name: &str, - ) -> Result { + ) -> Result { + use abi::DynSolType; + use abi::DynSolValue; + match (expected_type, value) { - (ParamType::Address, Value::Bytes(b)) => { - Ok(Token::Address(H160::from_slice(b.as_slice()))) + (DynSolType::Address, Value::Bytes(b)) => { + Ok(DynSolValue::Address(b.as_slice().try_into()?)) + } + (DynSolType::Bytes, Value::Bytes(b)) => Ok(DynSolValue::Bytes(b.as_ref().to_vec())), + (DynSolType::FixedBytes(size), Value::Bytes(b)) if b.len() == *size => { + DynSolValue::fixed_bytes_from_slice(b.as_ref()) + } + (DynSolType::String, Value::String(s)) => Ok(DynSolValue::String(s.to_string())), + (DynSolType::Bool, Value::Bool(b)) => Ok(DynSolValue::Bool(*b)), + (DynSolType::Int(_), Value::Int(i)) => { + let x = abi::I256::try_from(*i)?; + Ok(DynSolValue::Int(x, x.bits() as usize)) + } + (DynSolType::Int(_), Value::Int8(i)) => { + let x = abi::I256::try_from(*i)?; + Ok(DynSolValue::Int(x, x.bits() as usize)) + } + (DynSolType::Int(_), Value::BigInt(i)) => { + let x = abi::I256::from_limbs(i.to_signed_u256().0); + Ok(DynSolValue::Int(x, x.bits() as usize)) } - (ParamType::Bytes, Value::Bytes(b)) => Ok(Token::Bytes(b.as_ref().to_vec())), - (ParamType::FixedBytes(size), Value::Bytes(b)) if b.len() == *size => { - Ok(Token::FixedBytes(b.as_ref().to_vec())) + (DynSolType::Uint(_), Value::Int(i)) if *i >= 0 => { + let x = abi::U256::try_from(*i)?; + Ok(DynSolValue::Uint(x, x.bit_len())) } - (ParamType::String, Value::String(s)) => Ok(Token::String(s.to_string())), - (ParamType::Bool, Value::Bool(b)) => Ok(Token::Bool(*b)), - (ParamType::Int(_), Value::Int(i)) => Ok(Token::Int((*i).into())), - (ParamType::Int(_), Value::Int8(i)) => Ok(Token::Int((*i).into())), - (ParamType::Int(_), Value::BigInt(i)) => Ok(Token::Int(i.to_signed_u256())), - (ParamType::Uint(_), Value::Int(i)) if *i >= 0 => Ok(Token::Uint((*i).into())), - (ParamType::Uint(_), Value::BigInt(i)) if i.sign() == Sign::Plus => { - Ok(Token::Uint(i.to_unsigned_u256())) + (DynSolType::Uint(_), Value::BigInt(i)) if i.sign() == Sign::Plus => { + let x = abi::U256::from_limbs(i.to_unsigned_u256().0); + Ok(DynSolValue::Uint(x, x.bit_len())) } - (ParamType::Array(inner_type), Value::List(values)) => { + (DynSolType::Array(inner_type), Value::List(values)) => { self.process_entity_array_values(values, inner_type.as_ref(), param_name) } _ => Err(anyhow!( @@ -345,17 +385,17 @@ impl CallDecl { fn process_entity_array_values( &self, values: &[Value], - inner_type: &ParamType, + inner_type: &abi::DynSolType, param_name: &str, - ) -> Result { - let tokens: Result, Error> = values + ) -> Result { + let tokens: Result, Error> = values .iter() .enumerate() .map(|(idx, v)| { self.convert_entity_value_to_token(v, inner_type, &format!("{param_name}[{idx}]")) }) .collect(); - Ok(Token::Array(tokens?)) + Ok(abi::DynSolValue::Array(tokens?)) } } @@ -531,8 +571,8 @@ pub struct DeclaredCall { label: String, contract_name: String, address: Address, - function: Function, - args: Vec, + function: abi::Function, + args: Vec, } impl DeclaredCall { @@ -540,8 +580,8 @@ impl DeclaredCall { mapping: &dyn FindMappingABI, call_decls: &CallDecls, log: &Log, - params: &[LogParam], - ) -> Result, anyhow::Error> { + params: &[abi::DynSolParam], + ) -> Result, Error> { Self::create_calls(mapping, call_decls, |decl, _| { Ok(( decl.address_for_log(log, params)?, @@ -554,13 +594,13 @@ impl DeclaredCall { mapping: &dyn FindMappingABI, call_decls: &CallDecls, entity: &EntitySourceOperation, - ) -> Result, anyhow::Error> { + ) -> Result, Error> { Self::create_calls(mapping, call_decls, |decl, function| { let param_types = function .inputs .iter() - .map(|param| param.kind.clone()) - .collect::>(); + .map(|param| param.selector_type().parse()) + .collect::, _>>()?; Ok(( decl.address_for_entity_handler(entity)?, @@ -580,7 +620,7 @@ impl DeclaredCall { get_address_and_args: F, ) -> Result, anyhow::Error> where - F: Fn(&CallDecl, &Function) -> Result<(Address, Vec), anyhow::Error>, + F: Fn(&CallDecl, &abi::Function) -> Result<(Address, Vec), anyhow::Error>, { let mut calls = Vec::new(); for decl in call_decls.decls.iter() { @@ -618,8 +658,8 @@ pub struct ContractCall { pub contract_name: String, pub address: Address, pub block_ptr: BlockPtr, - pub function: Function, - pub args: Vec, + pub function: abi::Function, + pub args: Vec, pub gas: Option, } diff --git a/graph/src/lib.rs b/graph/src/lib.rs index ee288c5729a..55a2994f717 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -37,8 +37,11 @@ pub mod env; pub mod ipfs; +pub mod abi; + /// Wrapper for spawning tasks that abort on panic, which is our default. mod task_spawn; + pub use task_spawn::{ block_on, spawn, spawn_allow_panic, spawn_blocking, spawn_blocking_allow_panic, spawn_thread, }; @@ -82,7 +85,6 @@ pub mod prelude { pub use chrono; pub use diesel; pub use envconfig; - pub use ethabi; pub use hex; pub use lazy_static::lazy_static; pub use prost; diff --git a/runtime/test/src/common.rs b/runtime/test/src/common.rs index 461d4a08256..c2a7d3a231b 100644 --- a/runtime/test/src/common.rs +++ b/runtime/test/src/common.rs @@ -1,4 +1,3 @@ -use ethabi::Contract; use graph::blockchain::BlockTime; use graph::components::store::DeploymentLocator; use graph::components::subgraph::SharedProofOfIndexing; @@ -82,7 +81,7 @@ fn mock_host_exports( fn mock_abi() -> MappingABI { MappingABI { name: "mock_abi".to_string(), - contract: Contract::load( + contract: serde_json::from_str( r#"[ { "inputs": [ @@ -93,8 +92,7 @@ fn mock_abi() -> MappingABI { ], "type": "constructor" } - ]"# - .as_bytes(), + ]"#, ) .unwrap(), } diff --git a/runtime/test/src/test/abi.rs b/runtime/test/src/test/abi.rs index b681287c50c..ac733bad554 100644 --- a/runtime/test/src/test/abi.rs +++ b/runtime/test/src/test/abi.rs @@ -1,4 +1,5 @@ -use graph::prelude::{ethabi::Token, web3::types::U256}; +use graph::abi; +use graph::prelude::web3::types::U256; use graph_runtime_wasm::asc_abi::class::{ ArrayBuffer, AscAddress, AscEnum, AscEnumArray, EthereumValueKind, StoreValueKind, TypedArray, }; @@ -178,9 +179,9 @@ async fn abi_bytes_and_fixed_bytes_v0_0_5() { test_abi_bytes_and_fixed_bytes(API_VERSION_0_0_5).await; } -async fn test_abi_ethabi_token_identity(api_version: Version) { +async fn test_abi_alloy_token_identity(api_version: Version) { let mut instance = test_module( - "abiEthabiTokenIdentity", + "abiAlloyTokenIdentity", mock_data_source( &wasm_file_path("abi_token.wasm", api_version.clone()), api_version.clone(), @@ -190,8 +191,8 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { .await; // Token::Address - let address = H160([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); - let token_address = Token::Address(address); + let address = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; + let token_address = abi::DynSolValue::Address(address.into()); let new_address_obj: AscPtr = instance.invoke_export1("token_to_address", &token_address); @@ -202,7 +203,7 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_eq!(token_address, new_token); // Token::Bytes - let token_bytes = Token::Bytes(vec![42, 45, 7, 245, 45]); + let token_bytes = abi::DynSolValue::Bytes(vec![42, 45, 7, 245, 45]); let new_bytes_obj: AscPtr = instance.invoke_export1("token_to_bytes", &token_bytes); let new_token_ptr = instance.takes_ptr_returns_ptr("token_from_bytes", new_bytes_obj); @@ -211,7 +212,8 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_eq!(token_bytes, new_token); // Token::Int - let int_token = Token::Int(U256([256, 453452345, 0, 42])); + let int = abi::I256::from_limbs([256, 453452345, 0, 42]); + let int_token = abi::DynSolValue::Int(int, int.bits() as usize); let new_int_obj: AscPtr = instance.invoke_export1("token_to_int", &int_token); let new_token_ptr = instance.takes_ptr_returns_ptr("token_from_int", new_int_obj); @@ -220,7 +222,8 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_eq!(int_token, new_token); // Token::Uint - let uint_token = Token::Uint(U256([256, 453452345, 0, 42])); + let uint = abi::U256::from_limbs([256, 453452345, 0, 42]); + let uint_token = abi::DynSolValue::Uint(uint, uint.bit_len()); let new_uint_obj: AscPtr = instance.invoke_export1("token_to_uint", &uint_token); let new_token_ptr = instance.takes_ptr_returns_ptr("token_from_uint", new_uint_obj); @@ -230,7 +233,7 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_ne!(uint_token, int_token); // Token::Bool - let token_bool = Token::Bool(true); + let token_bool = abi::DynSolValue::Bool(true); let token_bool_ptr = instance.asc_new(&token_bool).unwrap(); let func = instance @@ -251,7 +254,7 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_eq!(token_bool, new_token); // Token::String - let token_string = Token::String("漢字Go🇧🇷".into()); + let token_string = abi::DynSolValue::String("漢字Go🇧🇷".into()); let new_string_obj: AscPtr = instance.invoke_export1("token_to_string", &token_string); let new_token_ptr = instance.takes_ptr_returns_ptr("token_from_string", new_string_obj); @@ -260,13 +263,13 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { assert_eq!(token_string, new_token); // Token::Array - let token_array = Token::Array(vec![token_address, token_bytes, token_bool]); - let token_array_nested = Token::Array(vec![token_string, token_array]); + let token_array = abi::DynSolValue::Array(vec![token_address, token_bytes, token_bool]); + let token_array_nested = abi::DynSolValue::Array(vec![token_string, token_array]); let new_array_obj: AscEnumArray = instance.invoke_export1("token_to_array", &token_array_nested); let new_token_ptr = instance.takes_ptr_returns_ptr("token_from_array", new_array_obj); - let new_token: Token = instance.asc_get(new_token_ptr).unwrap(); + let new_token: abi::DynSolValue = instance.asc_get(new_token_ptr).unwrap(); assert_eq!(new_token, token_array_nested); } @@ -274,15 +277,15 @@ async fn test_abi_ethabi_token_identity(api_version: Version) { /// Test a roundtrip Token -> Payload -> Token identity conversion through asc, /// and assert the final token is the same as the starting one. #[tokio::test] -async fn abi_ethabi_token_identity_v0_0_4() { - test_abi_ethabi_token_identity(API_VERSION_0_0_4).await; +async fn abi_alloy_token_identity_v0_0_4() { + test_abi_alloy_token_identity(API_VERSION_0_0_4).await; } /// Test a roundtrip Token -> Payload -> Token identity conversion through asc, /// and assert the final token is the same as the starting one. #[tokio::test] -async fn abi_ethabi_token_identity_v0_0_5() { - test_abi_ethabi_token_identity(API_VERSION_0_0_5).await; +async fn abi_alloy_token_identity_v0_0_5() { + test_abi_alloy_token_identity(API_VERSION_0_0_5).await; } async fn test_abi_store_value(api_version: Version) { diff --git a/runtime/wasm/Cargo.toml b/runtime/wasm/Cargo.toml index dfbd7983b1c..2ca24759d0d 100644 --- a/runtime/wasm/Cargo.toml +++ b/runtime/wasm/Cargo.toml @@ -5,7 +5,6 @@ edition.workspace = true [dependencies] async-trait = "0.1.50" -ethabi = "17.2" hex = "0.4.3" graph = { path = "../../graph" } bs58 = "0.4.0" diff --git a/runtime/wasm/src/asc_abi/class.rs b/runtime/wasm/src/asc_abi/class.rs index 1fae1ad9ce0..1e69c9690df 100644 --- a/runtime/wasm/src/asc_abi/class.rs +++ b/runtime/wasm/src/asc_abi/class.rs @@ -1,5 +1,4 @@ -use ethabi; - +use graph::abi; use graph::{ data::store::{self, scalar::Timestamp}, runtime::{ @@ -535,21 +534,25 @@ pub enum EthereumValueKind { FixedArray, Array, Tuple, + Function, } impl EthereumValueKind { - pub(crate) fn get_kind(token: ðabi::Token) -> Self { - match token { - ethabi::Token::Address(_) => EthereumValueKind::Address, - ethabi::Token::FixedBytes(_) => EthereumValueKind::FixedBytes, - ethabi::Token::Bytes(_) => EthereumValueKind::Bytes, - ethabi::Token::Int(_) => EthereumValueKind::Int, - ethabi::Token::Uint(_) => EthereumValueKind::Uint, - ethabi::Token::Bool(_) => EthereumValueKind::Bool, - ethabi::Token::String(_) => EthereumValueKind::String, - ethabi::Token::FixedArray(_) => EthereumValueKind::FixedArray, - ethabi::Token::Array(_) => EthereumValueKind::Array, - ethabi::Token::Tuple(_) => EthereumValueKind::Tuple, + pub(crate) fn get_kind(value: &abi::DynSolValue) -> Self { + use graph::abi::DynSolValue; + + match value { + DynSolValue::Bool(_) => Self::Bool, + DynSolValue::Int(_, _) => Self::Int, + DynSolValue::Uint(_, _) => Self::Uint, + DynSolValue::FixedBytes(_, _) => Self::FixedBytes, + DynSolValue::Address(_) => Self::Address, + DynSolValue::Function(_) => Self::Function, + DynSolValue::Bytes(_) => Self::Bytes, + DynSolValue::String(_) => Self::String, + DynSolValue::Array(_) => Self::Array, + DynSolValue::FixedArray(_) => Self::FixedArray, + DynSolValue::Tuple(_) => Self::Tuple, } } } diff --git a/runtime/wasm/src/host_exports.rs b/runtime/wasm/src/host_exports.rs index 12099c55b7e..732deaa221b 100644 --- a/runtime/wasm/src/host_exports.rs +++ b/runtime/wasm/src/host_exports.rs @@ -11,6 +11,7 @@ use never::Never; use semver::Version; use web3::types::H160; +use graph::abi; use graph::blockchain::BlockTime; use graph::blockchain::Blockchain; use graph::components::store::{EnsLookup, GetScope, LoadRelatedRequest}; @@ -20,8 +21,6 @@ use graph::components::subgraph::{ use graph::data::store::{self}; use graph::data_source::{CausalityRegion, DataSource, EntityTypeAccess}; use graph::ensure; -use graph::prelude::ethabi::param_type::Reader; -use graph::prelude::ethabi::{decode, encode, Token}; use graph::prelude::serde_json; use graph::prelude::{slog::b, slog::record_static, *}; use graph::runtime::gas::{self, complexity, Gas, GasCounter}; @@ -1181,11 +1180,11 @@ impl HostExports { pub(crate) fn ethereum_encode( &self, - token: Token, + value: abi::DynSolValue, gas: &GasCounter, state: &mut BlockState, ) -> Result, DeterministicHostError> { - let encoded = encode(&[token]); + let encoded = value.abi_encode(); Self::track_gas_and_ops( gas, @@ -1203,7 +1202,7 @@ impl HostExports { data: Vec, gas: &GasCounter, state: &mut BlockState, - ) -> Result { + ) -> Result { Self::track_gas_and_ops( gas, state, @@ -1211,15 +1210,9 @@ impl HostExports { "ethereum_decode", )?; - let param_types = - Reader::read(&types).map_err(|e| anyhow::anyhow!("Failed to read types: {}", e))?; + let ty: abi::DynSolType = types.parse().context("Failed to read types")?; - decode(&[param_types], &data) - // The `.pop().unwrap()` here is ok because we're always only passing one - // `param_types` to `decode`, so the returned `Vec` has always size of one. - // We can't do `tokens[0]` because the value can't be moved out of the `Vec`. - .map(|mut tokens| tokens.pop().unwrap()) - .context("Failed to decode") + ty.abi_decode(&data).context("Failed to decode") } pub(crate) fn yaml_from_bytes( diff --git a/runtime/wasm/src/to_from/external.rs b/runtime/wasm/src/to_from/external.rs index 6bb7122613f..85074f492ca 100644 --- a/runtime/wasm/src/to_from/external.rs +++ b/runtime/wasm/src/to_from/external.rs @@ -1,5 +1,5 @@ -use ethabi; - +use graph::abi; +use graph::abi::DynSolValueExt; use graph::data::store::scalar::Timestamp; use graph::data::value::Word; use graph::prelude::{BigDecimal, BigInt}; @@ -163,32 +163,42 @@ impl ToAscObj>> for Vec { } } -impl ToAscObj> for ethabi::Token { +impl ToAscObj> for abi::DynSolValue { fn to_asc_obj( &self, heap: &mut H, gas: &GasCounter, ) -> Result, HostExportError> { - use ethabi::Token::*; - let kind = EthereumValueKind::get_kind(self); + let payload = match self { - Address(address) => asc_new::(heap, address, gas)?.to_payload(), - FixedBytes(bytes) | Bytes(bytes) => { - asc_new::(heap, &**bytes, gas)?.to_payload() - } - Int(uint) => { - let n = BigInt::from_signed_u256(uint); + Self::Bool(val) => *val as u64, + Self::Int(val, _) => { + let bytes = val.to_le_bytes::<32>(); + let n = BigInt::from_signed_bytes_le(&bytes)?; + asc_new(heap, &n, gas)?.to_payload() } - Uint(uint) => { - let n = BigInt::from_unsigned_u256(uint); + Self::Uint(val, _) => { + let bytes = val.to_le_bytes::<32>(); + let n = BigInt::from_unsigned_bytes_le(&bytes)?; + asc_new(heap, &n, gas)?.to_payload() } - Bool(b) => *b as u64, - String(string) => asc_new(heap, &**string, gas)?.to_payload(), - FixedArray(tokens) | Array(tokens) => asc_new(heap, &**tokens, gas)?.to_payload(), - Tuple(tokens) => asc_new(heap, &**tokens, gas)?.to_payload(), + Self::FixedBytes(val, _) => { + asc_new::(heap, val.as_slice(), gas)?.to_payload() + } + Self::Address(val) => { + asc_new::(heap, val.as_slice(), gas)?.to_payload() + } + Self::Function(val) => { + asc_new::(heap, val.as_slice(), gas)?.to_payload() + } + Self::Bytes(val) => asc_new::(heap, &**val, gas)?.to_payload(), + Self::String(val) => asc_new(heap, &**val, gas)?.to_payload(), + Self::Array(values) => asc_new(heap, &**values, gas)?.to_payload(), + Self::FixedArray(values) => asc_new(heap, &**values, gas)?.to_payload(), + Self::Tuple(values) => asc_new(heap, &**values, gas)?.to_payload(), }; Ok(AscEnum { @@ -199,57 +209,78 @@ impl ToAscObj> for ethabi::Token { } } -impl FromAscObj> for ethabi::Token { +impl FromAscObj> for abi::DynSolValue { fn from_asc_obj( asc_enum: AscEnum, heap: &H, gas: &GasCounter, depth: usize, ) -> Result { - use ethabi::Token; - let payload = asc_enum.payload; - Ok(match asc_enum.kind { - EthereumValueKind::Bool => Token::Bool(bool::from(payload)), + + let value = match asc_enum.kind { EthereumValueKind::Address => { let ptr: AscPtr = AscPtr::from(payload); - Token::Address(asc_get(heap, ptr, gas, depth)?) + let bytes: [u8; 20] = asc_get(heap, ptr, gas, depth)?; + + Self::Address(bytes.into()) } EthereumValueKind::FixedBytes => { let ptr: AscPtr = AscPtr::from(payload); - Token::FixedBytes(asc_get(heap, ptr, gas, depth)?) + let bytes: Vec = asc_get(heap, ptr, gas, depth)?; + + Self::fixed_bytes_from_slice(&bytes)? } EthereumValueKind::Bytes => { let ptr: AscPtr = AscPtr::from(payload); - Token::Bytes(asc_get(heap, ptr, gas, depth)?) + let bytes: Vec = asc_get(heap, ptr, gas, depth)?; + + Self::Bytes(bytes) } EthereumValueKind::Int => { let ptr: AscPtr = AscPtr::from(payload); let n: BigInt = asc_get(heap, ptr, gas, depth)?; - Token::Int(n.to_signed_u256()) + let x = abi::I256::from_limbs(n.to_signed_u256().0); + + Self::Int(x, x.bits() as usize) } EthereumValueKind::Uint => { let ptr: AscPtr = AscPtr::from(payload); let n: BigInt = asc_get(heap, ptr, gas, depth)?; - Token::Uint(n.to_unsigned_u256()) + let x = abi::U256::from_limbs(n.to_unsigned_u256().0); + + Self::Uint(x, x.bit_len()) } + EthereumValueKind::Bool => Self::Bool(bool::from(payload)), EthereumValueKind::String => { let ptr: AscPtr = AscPtr::from(payload); - Token::String(asc_get(heap, ptr, gas, depth)?) + + Self::String(asc_get(heap, ptr, gas, depth)?) } EthereumValueKind::FixedArray => { let ptr: AscEnumArray = AscPtr::from(payload); - Token::FixedArray(asc_get(heap, ptr, gas, depth)?) + + Self::FixedArray(asc_get(heap, ptr, gas, depth)?) } EthereumValueKind::Array => { let ptr: AscEnumArray = AscPtr::from(payload); - Token::Array(asc_get(heap, ptr, gas, depth)?) + + Self::Array(asc_get(heap, ptr, gas, depth)?) } EthereumValueKind::Tuple => { let ptr: AscEnumArray = AscPtr::from(payload); - Token::Tuple(asc_get(heap, ptr, gas, depth)?) + + Self::Tuple(asc_get(heap, ptr, gas, depth)?) } - }) + EthereumValueKind::Function => { + let ptr: AscPtr = AscPtr::from(payload); + let bytes: [u8; 24] = asc_get(heap, ptr, gas, depth)?; + + Self::Function(bytes.into()) + } + }; + + Ok(value) } } diff --git a/store/postgres/src/chain_store.rs b/store/postgres/src/chain_store.rs index db83199a56c..8424ed3daf0 100644 --- a/store/postgres/src/chain_store.rs +++ b/store/postgres/src/chain_store.rs @@ -100,8 +100,8 @@ mod data { use graph::blockchain::{Block, BlockHash}; use graph::data::store::scalar::Bytes; use graph::internal_error; - use graph::prelude::ethabi::ethereum_types::H160; use graph::prelude::transaction_receipt::LightTransactionReceipt; + use graph::prelude::web3::types::H160; use graph::prelude::web3::types::H256; use graph::prelude::{ serde_json as json, BlockNumber, BlockPtr, CachedEthereumCall, Error, StoreError, diff --git a/store/test-store/Cargo.toml b/store/test-store/Cargo.toml index 2435b447570..58071829315 100644 --- a/store/test-store/Cargo.toml +++ b/store/test-store/Cargo.toml @@ -19,3 +19,4 @@ prost-types = { workspace = true } [dev-dependencies] hex = "0.4.3" pretty_assertions = "1.4.1" +serde_json = { workspace = true } diff --git a/store/test-store/tests/postgres/store.rs b/store/test-store/tests/postgres/store.rs index 28fd05da18f..cf9c2bae428 100644 --- a/store/test-store/tests/postgres/store.rs +++ b/store/test-store/tests/postgres/store.rs @@ -15,7 +15,6 @@ use graph::data::subgraph::*; use graph::{ blockchain::DataSource, components::store::{BlockStore as _, EntityFilter, EntityOrder, EntityQuery, StatusStore}, - prelude::ethabi::Contract, }; use graph::{data::store::scalar, semver::Version}; use graph::{entity, prelude::*}; @@ -1059,19 +1058,18 @@ fn mock_data_source() -> graph_chain_ethereum::DataSource { fn mock_abi() -> MappingABI { MappingABI { name: "mock_abi".to_string(), - contract: Contract::load( + contract: serde_json::from_str( r#"[ - { - "inputs": [ - { - "name": "a", - "type": "address" - } - ], - "type": "constructor" - } - ]"# - .as_bytes(), + { + "inputs": [ + { + "name": "a", + "type": "address" + } + ], + "type": "constructor" + } + ]"#, ) .unwrap(), } diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index ddf950bd273..476bc73498b 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -6,16 +6,18 @@ use super::{ test_ptr, CommonChainConfig, MutexBlockStreamBuilder, NoopAdapterSelector, NoopRuntimeAdapterBuilder, StaticBlockRefetcher, StaticStreamBuilder, Stores, TestChain, }; +use graph::abi; +use graph::blockchain::block_stream::BlockWithTriggers; use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation}; use graph::blockchain::client::ChainClient; use graph::blockchain::{BlockPtr, Trigger, TriggersAdapterSelector}; use graph::cheap_clone::CheapClone; use graph::data_source::subgraph; -use graph::prelude::ethabi::ethereum_types::H256; +use graph::prelude::web3::types::H256; +use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Log, Transaction, H160}; -use graph::prelude::{ethabi, tiny_keccak, DeploymentHash, Entity, LightEthereumBlock, ENV_VARS}; +use graph::prelude::{tiny_keccak, DeploymentHash, Entity, LightEthereumBlock, ENV_VARS}; use graph::schema::EntityType; -use graph::{blockchain::block_stream::BlockWithTriggers, prelude::ethabi::ethereum_types::U64}; use graph_chain_ethereum::network::EthereumNetworkAdapters; use graph_chain_ethereum::trigger::LogRef; use graph_chain_ethereum::Chain; @@ -143,7 +145,7 @@ pub fn push_test_log(block: &mut BlockWithTriggers, payload: impl Into Date: Wed, 7 May 2025 22:58:37 +0300 Subject: [PATCH 02/44] bump crate version --- Cargo.lock | 305 ++++++++++++++++++++++------------ Cargo.toml | 2 +- graph/src/abi/event_ext.rs | 2 +- graph/src/abi/function_ext.rs | 4 +- 4 files changed, 204 insertions(+), 109 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d0d79f8bf0..26be3191397 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,9 +53,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2cc5aeb8dfa1e451a49fac87bc4b86c5de40ebea153ed88e83eb92b8151e74" +checksum = "3a0be470ab41e3aaed6c54dbb2b6224d3048de467d8009cf9d5d32a8b8957ef7" dependencies = [ "alloy-consensus", "alloy-contract", @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.1.69" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" +checksum = "7734aecfc58a597dde036e4c5cace2ae43e2f8bf3d406b022a1ef34da178dd49" dependencies = [ "alloy-primitives", "num_enum", @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e32ef5c74bbeb1733c37f4ac7f866f8c8af208b7b4265e21af609dcac5bd5e" +checksum = "3a4fbb5e716faa10fc4e7a122307afcf55bae7272fc69286ee3eee881f757c66" dependencies = [ "alloy-eips", "alloy-primitives", @@ -97,15 +97,22 @@ dependencies = [ "alloy-trie", "auto_impl", "c-kzg", - "derive_more 1.0.0", + "derive_more 2.0.1", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "secp256k1 0.30.0", "serde", + "serde_with 3.12.0", + "thiserror 2.0.12", ] [[package]] name = "alloy-consensus-any" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa13b7b1e1e3fedc42f0728103bfa3b4d566d3d42b606db449504d88dbdbdcf" +checksum = "42c04d03d9ee6b6768cad687df5a360fc58714f39a37c971b907a8965717636d" dependencies = [ "alloy-consensus", "alloy-eips", @@ -117,10 +124,11 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6180fb232becdea70fad57c63b6967f01f74ab9595671b870f504116dd29de" +checksum = "e0ff39ab8bf0d23caa41ec1898d80ad1bcb037c94a048141ac4a961980164e65" dependencies = [ + "alloy-consensus", "alloy-dyn-abi", "alloy-json-abi", "alloy-network", @@ -137,9 +145,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8bcce99ad10fe02640cfaec1c6bc809b837c783c1d52906aa5af66e2a196f6" +checksum = "24b2817489e4391d8c0bdf043c842164855e3d697de7a8e9edf24aa30b153ac5" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -150,9 +158,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb8e762aefd39a397ff485bc86df673465c4ad3ec8819cc60833a8a3ba5cdc87" +checksum = "4f90b63261b7744642f6075ed17db6de118eecbe9516ea6c6ffd444b80180b75" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -167,21 +175,22 @@ dependencies = [ [[package]] name = "alloy-eip2124" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675264c957689f0fd75f5993a73123c2cc3b5c235a38f5b9037fe6c826bfb2c0" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ "alloy-primitives", "alloy-rlp", "crc", + "serde", "thiserror 2.0.12", ] [[package]] name = "alloy-eip2930" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -190,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" +checksum = "804cefe429015b4244966c006d25bda5545fa9db5990e9c9079faf255052f50a" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -202,9 +211,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5591581ca2ab0b3e7226a4047f9a1bfcf431da1d0cce3752fda609fea3c27e37" +checksum = "22c3699f23cea35d97a0a911b42c3cfd54dd95233df09307f5ebe52e0a74ad6e" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -214,17 +223,17 @@ dependencies = [ "alloy-serde", "auto_impl", "c-kzg", - "derive_more 1.0.0", - "once_cell", + "derive_more 2.0.1", + "either", "serde", "sha2", ] [[package]] name = "alloy-genesis" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cded3a2d4bd7173f696458c5d4c98c18a628dfcc9f194385e80a486e412e2e0" +checksum = "24c5a4e3f60f0b53b5dbd13904694e775a23ff98a43d6dd640b753b72669b993" dependencies = [ "alloy-eips", "alloy-primitives", @@ -235,9 +244,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6beff64ad0aa6ad1019a3db26fef565aefeb011736150ab73ed3366c3cfd1b" +checksum = "0068ae277f5ee3153a95eaea8ff10e188ed8ccde9b7f9926305415a2c0ab2442" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -247,9 +256,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762414662d793d7aaa36ee3af6928b6be23227df1681ce9c039f6f11daadef64" +checksum = "ea71d308c1f3e42172c7fe9dccc6e63d97fa0cfd21d21f73c04d5e2640826f64" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -261,9 +270,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be03f2ebc00cf88bd06d3c6caf387dceaa9c7e6b268216779fa68a9bf8ab4e6" +checksum = "ddd432f53775e6ef85cfc8a3c90f174786bdc15d5cac379dcea01bd0e6f93edc" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -278,6 +287,7 @@ dependencies = [ "alloy-sol-types", "async-trait", "auto_impl", + "derive_more 2.0.1", "futures-utils-wasm", "serde", "serde_json", @@ -286,9 +296,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a00ce618ae2f78369918be0c20f620336381502c83b6ed62c2f7b2db27698b0" +checksum = "0b2dea138d01f0e9739dee905a9e40a0f2347dd217360d813b6b7967ee8c0a8e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -299,9 +309,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" +checksum = "6a12fe11d0b8118e551c29e1a67ccb6d01cc07ef08086df30f07487146de6fa1" dependencies = [ "alloy-rlp", "bytes", @@ -316,7 +326,7 @@ dependencies = [ "keccak-asm", "paste", "proptest", - "rand 0.8.5", + "rand 0.9.1", "ruint", "rustc-hash 2.1.1", "serde", @@ -326,9 +336,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbe0a2acff0c4bd1669c71251ce10fc455cbffa1b4d0a817d5ea4ba7e5bb3db7" +checksum = "0c1e1dc8a0a368a62455b526a037557b1e57c7fda652748e5e2c66db517906ed" dependencies = [ "alloy-chains", "alloy-consensus", @@ -339,6 +349,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-client", "alloy-rpc-types-eth", + "alloy-signer", "alloy-sol-types", "alloy-transport", "alloy-transport-http", @@ -346,6 +357,7 @@ dependencies = [ "async-trait", "auto_impl", "dashmap", + "either", "futures 0.3.31", "futures-utils-wasm", "lru", @@ -385,14 +397,15 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37cc3c7883dc41be1b01460127ad7930466d0a4bb6ba15a02ee34d2745e2d7c" +checksum = "97da6111d0232cc890aa4d334b5e427aa25491cf34adbe9806fa440a6f32650f" dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", "alloy-transport-http", + "async-stream", "futures 0.3.31", "pin-project", "reqwest", @@ -402,15 +415,16 @@ dependencies = [ "tokio-stream", "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", + "tracing-futures", "url", "wasmtimer", ] [[package]] name = "alloy-rpc-types" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f18e68a3882f372e045ddc89eb455469347767d17878ca492cfbac81e71a111" +checksum = "835291d2f5423e02f755872b329c0bae97743936f596749f6fb6f0cf4de1324e" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -420,9 +434,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318ae46dd12456df42527c3b94c1ae9001e1ceb707f7afe2c7807ac4e49ebad9" +checksum = "43c8536c15442b001046dcaff415067600231261e7c53767e74e69d15f72f651" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -431,9 +445,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4dbee4d82f8a22dde18c28257bed759afeae7ba73da4a1479a039fd1445d04" +checksum = "da690eafe37fe096037f8820b6bf2382f3ea68120d06a4253e4ac725a7e652dd" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -451,9 +465,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8732058f5ca28c1d53d241e8504620b997ef670315d7c8afab856b3e3b80d945" +checksum = "261be2da2ef0bbbf80eed153c995822725cbef193e49eb251e2bf72cac29dbaf" dependencies = [ "alloy-primitives", "serde", @@ -462,9 +476,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f96b3526fdd779a4bd0f37319cfb4172db52a7ac24cdbb8804b72091c18e1701" +checksum = "6fdf929ce72d18aa40974ecaa2cd77c5062a0baa105fdb95e6aa5609642d7210" dependencies = [ "alloy-primitives", "async-trait", @@ -477,9 +491,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe8f78cd6b7501c7e813a1eb4a087b72d23af51f5bb66d4e948dc840bdd207d8" +checksum = "94910e0d75f086d4ed15d6a884170f648c28d06e4a8516156ea90204c0560595" dependencies = [ "alloy-consensus", "alloy-network", @@ -493,9 +507,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10ae8e9a91d328ae954c22542415303919aabe976fe7a92eb06db1b68fd59f2" +checksum = "5d3ef8e0d622453d969ba3cded54cf6800efdc85cb929fe22c5bdf8335666757" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -507,9 +521,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ad5da86c127751bc607c174d6c9fe9b85ef0889a9ca0c641735d77d4f98f26" +checksum = "f0e84bd0693c69a8fbe3ec0008465e029c6293494df7cb07580bf4a33eff52e1" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -526,9 +540,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3d30f0d3f9ba3b7686f3ff1de9ee312647aac705604417a2f40c604f409a9e" +checksum = "f3de663412dadf9b64f4f92f507f78deebcc92339d12cf15f88ded65d41c7935" dependencies = [ "alloy-json-abi", "const-hex", @@ -544,9 +558,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" +checksum = "251273c5aa1abb590852f795c938730fa641832fc8fa77b5478ed1bf11b6097e" dependencies = [ "serde", "winnow 0.7.9", @@ -554,9 +568,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43d5e60466a440230c07761aa67671d4719d46f43be8ea6e7ed334d8db4a9ab" +checksum = "5460a975434ae594fe2b91586253c1beb404353b78f0a55bf124abcd79557b15" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -567,13 +581,17 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8d762eadce3e9b65eac09879430c6f4fce3736cac3cac123f9b1bf435ddd13" +checksum = "4b4f3654d5195c0c3f502bfd6ed299ea9eb5cb275d7a88d04ce0d189bca416b2" dependencies = [ "alloy-json-rpc", + "alloy-primitives", "base64 0.22.1", + "derive_more 2.0.1", + "futures 0.3.30", "futures-utils-wasm", + "parking_lot", "serde", "serde_json", "thiserror 2.0.12", @@ -586,9 +604,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.11.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20819c4cb978fb39ce6ac31991ba90f386d595f922f42ef888b4a18be190713e" +checksum = "70a9372fba202370973748d76c2891344cbacfb012d44a8ed62135ba53d4408e" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -601,14 +619,14 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.7.9" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" dependencies = [ "alloy-primitives", "alloy-rlp", "arrayvec 0.7.4", - "derive_more 1.0.0", + "derive_more 2.0.1", "nybbles", "serde", "smallvec", @@ -1251,6 +1269,22 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1390,9 +1424,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.3" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" dependencies = [ "blst", "cc", @@ -2072,33 +2106,13 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "derive_more-impl 1.0.0", -] - [[package]] name = "derive_more" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ - "derive_more-impl 2.0.1", -] - -[[package]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", + "derive_more-impl", ] [[package]] @@ -2314,15 +2328,19 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2339,6 +2357,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", + "serdect", "subtle", "zeroize", ] @@ -3200,7 +3219,7 @@ dependencies = [ "graph-runtime-wasm", "graph-server-index-node", "graph-store-postgres", - "secp256k1", + "secp256k1 0.21.3", "serde", "serde_yaml", "slog", @@ -3288,7 +3307,7 @@ dependencies = [ "lazy_static", "serde", "serde_json", - "serde_with", + "serde_with 2.3.3", ] [[package]] @@ -3448,6 +3467,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec 0.7.4", +] + [[package]] name = "hex-literal" version = "0.3.4" @@ -4114,6 +4142,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", + "serdect", "sha2", ] @@ -4562,9 +4591,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "opaque-debug" @@ -5285,6 +5314,7 @@ checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", + "serde", ] [[package]] @@ -5323,6 +5353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.1", + "serde", ] [[package]] @@ -5773,6 +5804,7 @@ dependencies = [ "der", "generic-array", "pkcs8", + "serdect", "subtle", "zeroize", ] @@ -5783,7 +5815,19 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c42e6f1735c5f00f51e43e28d6634141f2bcad10931b2609ddd74a86d751260" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.4.2", +] + +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys 0.10.1", + "serde", ] [[package]] @@ -5795,6 +5839,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -5953,10 +6006,40 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros", + "serde_with_macros 2.3.3", "time", ] +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.9.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros 3.12.0", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "serde_with_macros" version = "3.12.0" @@ -5982,6 +6065,16 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -6440,9 +6533,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.25" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4560533fbd6914b94a8fb5cc803ed6801c3455668db3b810702c57612bac9412" +checksum = "3d0f0d4760f4c2a0823063b2c70e97aa2ad185f57be195172ccc0e23c4b787c4" dependencies = [ "paste", "proc-macro2", @@ -7110,6 +7203,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ + "futures 0.3.30", + "futures-task", "pin-project", "tracing", ] @@ -7884,7 +7979,7 @@ dependencies = [ "pin-project", "reqwest", "rlp", - "secp256k1", + "secp256k1 0.21.3", "serde", "serde_json", "soketto", diff --git a/Cargo.toml b/Cargo.toml index 72eb515e309..2d5805eeacc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ repository = "https://github.com/graphprotocol/graph-node" license = "MIT OR Apache-2.0" [workspace.dependencies] -alloy = { version = "0.11.1", features = ["dyn-abi", "json-abi"] } +alloy = { version = "0.15.10", features = ["dyn-abi", "json-abi"] } anyhow = "1.0" async-graphql = { version = "7.0.15", features = ["chrono"] } async-graphql-axum = "7.0.15" diff --git a/graph/src/abi/event_ext.rs b/graph/src/abi/event_ext.rs index ac03a778bef..59ae560a8a2 100644 --- a/graph/src/abi/event_ext.rs +++ b/graph/src/abi/event_ext.rs @@ -17,7 +17,7 @@ pub trait EventExt { impl EventExt for Event { fn decode_log(&self, log: &Log) -> Result> { let log_data = log_to_log_data(log)?; - let decoded_event = alloy::dyn_abi::EventExt::decode_log(self, &log_data, true)?; + let decoded_event = alloy::dyn_abi::EventExt::decode_log(self, &log_data)?; let mut indexed: VecDeque = decoded_event.indexed.into(); let mut body: VecDeque = decoded_event.body.into(); diff --git a/graph/src/abi/function_ext.rs b/graph/src/abi/function_ext.rs index 634ca9a08d6..3264dd10a35 100644 --- a/graph/src/abi/function_ext.rs +++ b/graph/src/abi/function_ext.rs @@ -65,13 +65,13 @@ impl FunctionExt for Function { fn abi_decode_input(&self, data: &[u8]) -> Result> { (self as &dyn alloy::dyn_abi::FunctionExt) - .abi_decode_input(data, true) + .abi_decode_input(data) .map_err(Into::into) } fn abi_decode_output(&self, data: &[u8]) -> Result> { (self as &dyn alloy::dyn_abi::FunctionExt) - .abi_decode_output(data, true) + .abi_decode_output(data) .map_err(Into::into) } From b65b0951fc8aecb9209e3d766ff6c15cecd83db8 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 18:05:44 +0530 Subject: [PATCH 03/44] Add alloy_rpc_types crate --- Cargo.lock | 2427 +++++++++++++++++++++---------------- Cargo.toml | 3 +- chain/ethereum/Cargo.toml | 2 + 3 files changed, 1362 insertions(+), 1070 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26be3191397..ed88a3b65f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,29 +12,20 @@ dependencies = [ "regex", ] -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli 0.29.0", -] - [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli 0.31.1", + "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" @@ -53,9 +44,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a0be470ab41e3aaed6c54dbb2b6224d3048de467d8009cf9d5d32a8b8957ef7" +checksum = "2b064bd1cea105e70557a258cd2b317731896753ec08edf51da2d1fced587b05" dependencies = [ "alloy-consensus", "alloy-contract", @@ -64,6 +55,7 @@ dependencies = [ "alloy-genesis", "alloy-network", "alloy-provider", + "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types", "alloy-serde", @@ -71,13 +63,15 @@ dependencies = [ "alloy-signer-local", "alloy-transport", "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", ] [[package]] name = "alloy-chains" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7734aecfc58a597dde036e4c5cace2ae43e2f8bf3d406b022a1ef34da178dd49" +checksum = "19a9cc9d81ace3da457883b0bdf76776e55f1b84219a9e9d55c27ad308548d3f" dependencies = [ "alloy-primitives", "num_enum", @@ -86,9 +80,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4fbb5e716faa10fc4e7a122307afcf55bae7272fc69286ee3eee881f757c66" +checksum = "32c3f3bc4f2a6b725970cd354e78e9738ea1e8961a91898f57bf6317970b1915" dependencies = [ "alloy-eips", "alloy-primitives", @@ -104,15 +98,15 @@ dependencies = [ "rand 0.8.5", "secp256k1 0.30.0", "serde", - "serde_with 3.12.0", + "serde_with", "thiserror 2.0.12", ] [[package]] name = "alloy-consensus-any" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42c04d03d9ee6b6768cad687df5a360fc58714f39a37c971b907a8965717636d" +checksum = "dda014fb5591b8d8d24cab30f52690117d238e52254c6fb40658e91ea2ccd6c3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -124,9 +118,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ff39ab8bf0d23caa41ec1898d80ad1bcb037c94a048141ac4a961980164e65" +checksum = "9668ce1176f0b87a5e5fc805b3d198954f495de2e99b70a44bed691ba2b0a9d8" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -135,6 +129,7 @@ dependencies = [ "alloy-network-primitives", "alloy-primitives", "alloy-provider", + "alloy-pubsub", "alloy-rpc-types-eth", "alloy-sol-types", "alloy-transport", @@ -145,9 +140,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b2817489e4391d8c0bdf043c842164855e3d697de7a8e9edf24aa30b153ac5" +checksum = "5968f48d7a62587cd874bd84034831da4f7f577ce5de984828e376766efc0f32" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -158,19 +153,18 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f90b63261b7744642f6075ed17db6de118eecbe9516ea6c6ffd444b80180b75" +checksum = "f9135eb501feccf7f4cb8a183afd406a65483fdad7bbd7332d0470e5d725c92f" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", - "const-hex", "itoa", "serde", "serde_json", - "winnow 0.7.9", + "winnow", ] [[package]] @@ -199,21 +193,22 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804cefe429015b4244966c006d25bda5545fa9db5990e9c9079faf255052f50a" +checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" dependencies = [ "alloy-primitives", "alloy-rlp", + "k256", "serde", "thiserror 2.0.12", ] [[package]] name = "alloy-eips" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22c3699f23cea35d97a0a911b42c3cfd54dd95233df09307f5ebe52e0a74ad6e" +checksum = "2f7b2f7010581f29bcace81776cf2f0e022008d05a7d326884763f16f3044620" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -231,9 +226,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c5a4e3f60f0b53b5dbd13904694e775a23ff98a43d6dd640b753b72669b993" +checksum = "c7f723856b1c4ad5473f065650ab9be557c96fbc77e89180fbdac003e904a8d6" dependencies = [ "alloy-eips", "alloy-primitives", @@ -244,9 +239,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0068ae277f5ee3153a95eaea8ff10e188ed8ccde9b7f9926305415a2c0ab2442" +checksum = "8b26fdd571915bafe857fccba4ee1a4f352965800e46a53e4a5f50187b7776fa" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -256,9 +251,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea71d308c1f3e42172c7fe9dccc6e63d97fa0cfd21d21f73c04d5e2640826f64" +checksum = "ca1e31b50f4ed9a83689ae97263d366b15b935a67c4acb5dd46d5b1c3b27e8e6" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -270,9 +265,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd432f53775e6ef85cfc8a3c90f174786bdc15d5cac379dcea01bd0e6f93edc" +checksum = "879afc0f4a528908c8fe6935b2ab0bc07f77221a989186f71583f7592831689e" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -296,9 +291,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2dea138d01f0e9739dee905a9e40a0f2347dd217360d813b6b7967ee8c0a8e" +checksum = "ec185bac9d32df79c1132558a450d48f6db0bfb5adef417dbb1a0258153f879b" dependencies = [ "alloy-consensus", "alloy-eips", @@ -309,17 +304,17 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a12fe11d0b8118e551c29e1a67ccb6d01cc07ef08086df30f07487146de6fa1" +checksum = "a326d47106039f38b811057215a92139f46eef7983a4b77b10930a0ea5685b1e" dependencies = [ "alloy-rlp", "bytes", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "const-hex", "derive_more 2.0.1", "foldhash", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "indexmap 2.9.0", "itoa", "k256", @@ -336,9 +331,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1e1dc8a0a368a62455b526a037557b1e57c7fda652748e5e2c66db517906ed" +checksum = "b2d918534afe9cc050eabd8309c107dafd161aa77357782eca4f218bef08a660" dependencies = [ "alloy-chains", "alloy-consensus", @@ -347,12 +342,19 @@ dependencies = [ "alloy-network", "alloy-network-primitives", "alloy-primitives", + "alloy-pubsub", "alloy-rpc-client", + "alloy-rpc-types-anvil", + "alloy-rpc-types-debug", "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", "alloy-signer", "alloy-sol-types", "alloy-transport", "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", "async-stream", "async-trait", "auto_impl", @@ -373,38 +375,62 @@ dependencies = [ "wasmtimer", ] +[[package]] +name = "alloy-pubsub" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d77a92001c6267261a5e493d33db794b2206ebebf7c2dfbbe3825ebaec6a96d" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "bimap", + "futures 0.3.31", + "parking_lot", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "wasmtimer", +] + [[package]] name = "alloy-rlp" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" dependencies = [ "alloy-rlp-derive", - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bytes", ] [[package]] name = "alloy-rlp-derive" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" +checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "alloy-rpc-client" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97da6111d0232cc890aa4d334b5e427aa25491cf34adbe9806fa440a6f32650f" +checksum = "a15e30dcada47c04820b64f63de2423506c5c74f9ab59b115277ef5ad595a6fc" dependencies = [ "alloy-json-rpc", "alloy-primitives", + "alloy-pubsub", "alloy-transport", "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", "async-stream", "futures 0.3.31", "pin-project", @@ -422,9 +448,25 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.15.10" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa10e26554ad7f79a539a6a8851573aedec5289f1f03244aad0bdbc324bfe5c" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-anvil", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-anvil" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835291d2f5423e02f755872b329c0bae97743936f596749f6fb6f0cf4de1324e" +checksum = "d6cd4346521aa1e2e76963bbf0c1d311223f6eb565269359a6f9232c9044d1f7" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -434,20 +476,48 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c8536c15442b001046dcaff415067600231261e7c53767e74e69d15f72f651" +checksum = "7a5a8f1efd77116915dad61092f9ef9295accd0b0b251062390d9c4e81599344" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", "alloy-serde", ] +[[package]] +name = "alloy-rpc-types-debug" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c142af843da7422e5e979726dcfeb78064949fdc6cb651457cc95034806a52" +dependencies = [ + "alloy-primitives", + "serde", +] + +[[package]] +name = "alloy-rpc-types-engine" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246c225f878dbcb8ad405949a30c403b3bb43bdf974f7f0331b276f835790a5e" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "derive_more 2.0.1", + "jsonwebtoken", + "rand 0.8.5", + "serde", + "strum 0.27.1", +] + [[package]] name = "alloy-rpc-types-eth" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da690eafe37fe096037f8820b6bf2382f3ea68120d06a4253e4ac725a7e652dd" +checksum = "bc1323310d87f9d950fb3ff58d943fdf832f5e10e6f902f405c0eaa954ffbaf1" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -463,11 +533,37 @@ dependencies = [ "thiserror 2.0.12", ] +[[package]] +name = "alloy-rpc-types-trace" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d57f1b7da0af516ad2c02233ed1274527f9b0536dbda300acea2e8a1e7ac20c8" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "alloy-rpc-types-txpool" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f4239235c4afdd8fa930a757ed81816799ddcc93d4e33cd0dae3b44f83f3e" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-serde" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261be2da2ef0bbbf80eed153c995822725cbef193e49eb251e2bf72cac29dbaf" +checksum = "d05ace2ef3da874544c3ffacfd73261cdb1405d8631765deb991436a53ec6069" dependencies = [ "alloy-primitives", "serde", @@ -476,9 +572,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fdf929ce72d18aa40974ecaa2cd77c5062a0baa105fdb95e6aa5609642d7210" +checksum = "67fdabad99ad3c71384867374c60bcd311fc1bb90ea87f5f9c779fd8c7ec36aa" dependencies = [ "alloy-primitives", "async-trait", @@ -491,9 +587,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94910e0d75f086d4ed15d6a884170f648c28d06e4a8516156ea90204c0560595" +checksum = "acb3f4e72378566b189624d54618c8adf07afbcf39d5f368f4486e35a66725b3" dependencies = [ "alloy-consensus", "alloy-network", @@ -507,23 +603,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3ef8e0d622453d969ba3cded54cf6800efdc85cb929fe22c5bdf8335666757" +checksum = "d4be1ce1274ddd7fdfac86e5ece1b225e9bba1f2327e20fbb30ee6b9cc1423fe" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e84bd0693c69a8fbe3ec0008465e029c6293494df7cb07580bf4a33eff52e1" +checksum = "01e92f3708ea4e0d9139001c86c051c538af0146944a2a9c7181753bd944bf57" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -533,16 +629,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "syn-solidity", "tiny-keccak 2.0.2", ] [[package]] name = "alloy-sol-macro-input" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3de663412dadf9b64f4f92f507f78deebcc92339d12cf15f88ded65d41c7935" +checksum = "9afe1bd348a41f8c9b4b54dfb314886786d6201235b0b3f47198b9d910c86bb2" dependencies = [ "alloy-json-abi", "const-hex", @@ -552,44 +648,43 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.101", + "syn 2.0.102", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "251273c5aa1abb590852f795c938730fa641832fc8fa77b5478ed1bf11b6097e" +checksum = "d6195df2acd42df92a380a8db6205a5c7b41282d0ce3f4c665ecf7911ac292f1" dependencies = [ "serde", - "winnow 0.7.9", + "winnow", ] [[package]] name = "alloy-sol-types" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5460a975434ae594fe2b91586253c1beb404353b78f0a55bf124abcd79557b15" +checksum = "6185e98a79cf19010722f48a74b5a65d153631d2f038cabd250f4b9e9813b8ad" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-macro", - "const-hex", "serde", ] [[package]] name = "alloy-transport" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4f3654d5195c0c3f502bfd6ed299ea9eb5cb275d7a88d04ce0d189bca416b2" +checksum = "6964d85cd986cfc015b96887b89beed9e06d0d015b75ee2b7bfbd64341aab874" dependencies = [ "alloy-json-rpc", "alloy-primitives", "base64 0.22.1", "derive_more 2.0.1", - "futures 0.3.30", + "futures 0.3.31", "futures-utils-wasm", "parking_lot", "serde", @@ -604,9 +699,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a9372fba202370973748d76c2891344cbacfb012d44a8ed62135ba53d4408e" +checksum = "ef7c5ea7bda4497abe4ea92dcb8c76e9f052c178f3c82aa6976bcb264675f73c" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -617,6 +712,44 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-transport-ipc" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c506a002d77e522ccab7b7068089a16e24694ea04cb89c0bfecf3cc3603fccf" +dependencies = [ + "alloy-json-rpc", + "alloy-pubsub", + "alloy-transport", + "bytes", + "futures 0.3.31", + "interprocess", + "pin-project", + "serde", + "serde_json", + "tokio", + "tokio-util 0.7.15", + "tracing", +] + +[[package]] +name = "alloy-transport-ws" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ff1bb1182601fa5e7b0f8bac03dcd496441ed23859387731462b17511c6680" +dependencies = [ + "alloy-pubsub", + "alloy-transport", + "futures 0.3.31", + "http 1.3.1", + "rustls", + "serde_json", + "tokio", + "tokio-tungstenite", + "tracing", + "ws_stream_wasm", +] + [[package]] name = "alloy-trie" version = "0.8.1" @@ -625,7 +758,7 @@ checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" dependencies = [ "alloy-primitives", "alloy-rlp", - "arrayvec 0.7.4", + "arrayvec 0.7.6", "derive_more 2.0.1", "nybbles", "serde", @@ -650,9 +783,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -665,36 +798,37 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.59.0", ] [[package]] @@ -749,7 +883,7 @@ dependencies = [ "num-bigint 0.4.6", "num-traits", "paste", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "zeroize", ] @@ -841,9 +975,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -853,19 +987,13 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" dependencies = [ "serde", ] -[[package]] -name = "ascii" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" - [[package]] name = "ascii_utils" version = "0.9.3" @@ -884,9 +1012,9 @@ dependencies = [ [[package]] name = "async-graphql" -version = "7.0.15" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfff2b17d272a5e3e201feda444e2c24b011fa722951268d1bd8b9b5bc6dc449" +checksum = "036618f842229ba0b89652ffe425f96c7c16a49f7e3cb23b56fca7f61fd74980" dependencies = [ "async-graphql-derive", "async-graphql-parser", @@ -913,31 +1041,31 @@ dependencies = [ "serde_urlencoded", "static_assertions_next", "tempfile", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] name = "async-graphql-axum" -version = "7.0.15" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf2882c816094fef6e39d381b8e9b710e5943e7bdef5198496441d5083164fa" +checksum = "8725874ecfbf399e071150b8619c4071d7b2b7a2f117e173dddef53c6bdb6bb1" dependencies = [ "async-graphql", - "axum 0.8.3", + "axum 0.8.4", "bytes", "futures-util", "serde_json", "tokio", "tokio-stream", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "async-graphql-derive" -version = "7.0.15" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e5d0c6697def2f79ccbd972fb106b633173a6066e430b480e1ff9376a7561a" +checksum = "fd45deb3dbe5da5cdb8d6a670a7736d735ba65b455328440f236dfb113727a3d" dependencies = [ "Inflector", "async-graphql-parser", @@ -946,15 +1074,15 @@ dependencies = [ "proc-macro2", "quote", "strum 0.26.3", - "syn 2.0.101", - "thiserror 1.0.61", + "syn 2.0.102", + "thiserror 1.0.69", ] [[package]] name = "async-graphql-parser" -version = "7.0.15" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8531ee6d292c26df31c18c565ff22371e7bdfffe7f5e62b69537db0b8fd554dc" +checksum = "60b7607e59424a35dadbc085b0d513aa54ec28160ee640cf79ec3b634eba66d3" dependencies = [ "async-graphql-value", "pest", @@ -964,9 +1092,9 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.15" +version = "7.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741110dda927420a28fbc1c310543d3416f789a6ba96859c2c265843a0a96887" +checksum = "34ecdaff7c9cffa3614a9f9999bf9ee4c3078fe3ce4d6a6e161736b56febf2de" dependencies = [ "bytes", "indexmap 2.9.0", @@ -982,7 +1110,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1004,18 +1132,29 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures 0.3.31", + "pharos", + "rustc_version 0.4.1", ] [[package]] @@ -1049,27 +1188,27 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core 0.4.5", "bytes", "futures-util", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "itoa", "matchit 0.7.3", @@ -1079,17 +1218,17 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.1", - "tower 0.4.13", + "sync_wrapper", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "axum" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de45108900e1f9b9242f7f2e254aa3e2c029c921c258fe9e6b4217eeebd54288" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ "axum-core 0.5.2", "base64 0.22.1", @@ -1097,7 +1236,7 @@ dependencies = [ "form_urlencoded", "futures-util", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "hyper 1.6.0", "hyper-util", @@ -1113,7 +1252,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 1.0.1", + "sync_wrapper", "tokio", "tokio-tungstenite", "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1124,20 +1263,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1151,12 +1290,12 @@ dependencies = [ "bytes", "futures-core", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -1164,26 +1303,26 @@ dependencies = [ [[package]] name = "backon" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0b50b1b78dbadd44ab18b3c794e496f3a139abb9fbc27d9c94c4eebbb96496" +checksum = "302eaff5357a264a2c42f127ecb8bac761cf99749fc3dc95677e2743991f99e7" dependencies = [ "fastrand", ] [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ - "addr2line 0.22.0", - "cc", - "cfg-if 1.0.0", + "addr2line", + "cfg-if 1.0.1", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -1218,9 +1357,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "beef" @@ -1254,6 +1393,25 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bigdecimal" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" +dependencies = [ + "autocfg", + "libm", + "num-bigint 0.4.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + [[package]] name = "bit-set" version = "0.8.0" @@ -1287,15 +1445,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" @@ -1331,9 +1483,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec 0.7.6", "cc", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "constant_time_eq 0.3.1", ] @@ -1357,9 +1509,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" +checksum = "4fd49896f12ac9b6dcd7a5998466b9b58263a695a3dd1ecc1aaca2e12a90b080" dependencies = [ "cc", "glob", @@ -1384,9 +1536,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "serde", @@ -1394,18 +1546,18 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" dependencies = [ "allocator-api2", ] [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "byteorder" @@ -1439,9 +1591,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -1456,9 +1608,15 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" @@ -1484,14 +1642,14 @@ dependencies = [ "core2", "multibase", "multihash", - "unsigned-varint 0.8.0", + "unsigned-varint", ] [[package]] name = "clap" -version = "4.5.8" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -1499,9 +1657,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -1512,21 +1670,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cobs" @@ -1536,22 +1694,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "combine" -version = "3.8.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" -dependencies = [ - "ascii", - "byteorder", - "either", - "memchr", - "unreachable", -] +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" @@ -1564,7 +1709,7 @@ dependencies = [ "memchr", "pin-project-lite", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", ] [[package]] @@ -1576,17 +1721,17 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.0", + "unicode-width 0.2.1", "windows-sys 0.59.0", ] [[package]] name = "const-hex" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "cpufeatures", "hex", "proptest", @@ -1599,6 +1744,26 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1638,9 +1803,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -1667,14 +1832,14 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", ] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -1731,8 +1896,8 @@ dependencies = [ "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli 0.31.1", - "hashbrown 0.15.2", + "gimli", + "hashbrown 0.15.4", "log", "pulley-interpreter", "regalloc2", @@ -1817,9 +1982,9 @@ checksum = "85256fac1519a7d25a040c1d850fba67478f3f021ad5fdf738ba4425ee862dbf" [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1836,7 +2001,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", ] [[package]] @@ -1863,9 +2028,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1882,24 +2047,24 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" @@ -1935,9 +2100,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -1947,18 +2112,18 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ "memchr", ] [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -1966,27 +2131,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1995,7 +2160,7 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "crossbeam-utils", "hashbrown 0.14.5", "lock_api", @@ -2005,15 +2170,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-encoding-macro" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2021,12 +2186,12 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.102", ] [[package]] @@ -2074,9 +2239,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -2095,15 +2260,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version 0.4.0", - "syn 2.0.101", + "rustc_version 0.4.1", + "syn 2.0.102", ] [[package]] @@ -2124,18 +2289,18 @@ dependencies = [ "convert_case 0.7.1", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "unicode-xid", ] [[package]] name = "diesel" -version = "2.2.7" +version = "2.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04001f23ba8843dc315804fa324000376084dfb1c30794ff68dd279e6e5696d5" +checksum = "ff3e1edb1f37b4953dd5176916347289ed43d7119cc2e6c7c3f7849ff44ea506" dependencies = [ - "bigdecimal 0.3.1", - "bitflags 2.6.0", + "bigdecimal 0.4.8", + "bitflags", "byteorder", "chrono", "diesel_derives", @@ -2157,7 +2322,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2179,7 +2344,7 @@ dependencies = [ "dsl_auto_type", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2199,7 +2364,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" dependencies = [ - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2241,15 +2406,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "dirs-sys-next", ] [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] @@ -2260,20 +2425,20 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "dirs-sys-next", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users", - "windows-sys 0.48.0", + "redox_users 0.5.0", + "windows-sys 0.60.1", ] [[package]] @@ -2283,7 +2448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -2295,21 +2460,27 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] +[[package]] +name = "doctest-file" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" + [[package]] name = "dsl_auto_type" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0892a17df262a24294c382f0d5997571006e7a4348b4327557c4ff1cd4a8bccc" +checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b" dependencies = [ "darling", "either", "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2382,18 +2553,18 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -2401,14 +2572,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -2429,14 +2600,14 @@ checksum = "d4291f0c7220b67ad15e9d5300ba2f215cee504f0924d60e77c9d1c77e7a69b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -2461,7 +2632,7 @@ dependencies = [ "serde", "serde_json", "sha3", - "thiserror 1.0.61", + "thiserror 1.0.69", "uint 0.9.5", ] @@ -2515,9 +2686,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fastrlp" @@ -2525,7 +2696,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "auto_impl", "bytes", ] @@ -2536,7 +2707,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "auto_impl", "bytes", ] @@ -2595,9 +2766,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.0.30" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -2707,7 +2878,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2768,7 +2939,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.6.0", + "bitflags", "debugid", "fxhash", "serde", @@ -2788,33 +2959,31 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", + "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "gimli" version = "0.31.1" @@ -2844,7 +3013,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "time", ] @@ -2856,9 +3025,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" dependencies = [ "aho-corasick", "bstr", @@ -2913,7 +3082,7 @@ dependencies = [ "num-traits", "object_store", "parking_lot", - "petgraph 0.8.1", + "petgraph 0.8.2", "priority-queue", "prometheus", "prost", @@ -2922,7 +3091,7 @@ dependencies = [ "redis", "regex", "reqwest", - "semver 1.0.23", + "semver 1.0.26", "serde", "serde_derive", "serde_json", @@ -2966,6 +3135,8 @@ dependencies = [ name = "graph-chain-ethereum" version = "0.36.0" dependencies = [ + "alloy", + "alloy-rpc-types", "anyhow", "base64 0.22.1", "envconfig", @@ -2977,7 +3148,7 @@ dependencies = [ "jsonrpc-core", "prost", "prost-types", - "semver 1.0.23", + "semver 1.0.26", "serde", "thiserror 2.0.12", "tiny-keccak 1.5.0", @@ -3012,7 +3183,7 @@ dependencies = [ "lazy_static", "prost", "prost-types", - "semver 1.0.23", + "semver 1.0.26", "serde", "tokio", "tonic-build", @@ -3093,7 +3264,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3105,7 +3276,7 @@ dependencies = [ "graph-runtime-derive", "graph-runtime-wasm", "rand 0.9.1", - "semver 1.0.23", + "semver 1.0.26", "test-store", "wasmtime", ] @@ -3114,6 +3285,7 @@ dependencies = [ name = "graph-runtime-wasm" version = "0.36.0" dependencies = [ + "alloy", "anyhow", "async-trait", "bs58 0.4.0", @@ -3122,7 +3294,7 @@ dependencies = [ "hex", "never", "parity-wasm", - "semver 1.0.23", + "semver 1.0.26", "serde_yaml", "wasm-instrument", "wasmtime", @@ -3235,7 +3407,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3259,7 +3431,7 @@ dependencies = [ "anyhow", "async-graphql", "async-graphql-axum", - "axum 0.8.3", + "axum 0.8.4", "chrono", "diesel", "graph", @@ -3274,7 +3446,7 @@ dependencies = [ "test-store", "thiserror 2.0.12", "tokio", - "tower-http", + "tower-http 0.5.2", ] [[package]] @@ -3289,12 +3461,12 @@ dependencies = [ [[package]] name = "graphql-parser" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ebc8013b4426d5b81a4364c419a95ed0b404af2b82e2457de52d9348f0e474" +checksum = "7a818c0d883d7c0801df27be910917750932be279c7bc82dc541b8769425f409" dependencies = [ - "combine 3.8.1", - "thiserror 1.0.61", + "combine", + "thiserror 1.0.69", ] [[package]] @@ -3307,7 +3479,7 @@ dependencies = [ "lazy_static", "serde", "serde_json", - "serde_with 2.3.3", + "serde_with", ] [[package]] @@ -3336,15 +3508,15 @@ dependencies = [ "indexmap 2.9.0", "slab", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tracing", ] [[package]] name = "h2" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -3355,7 +3527,7 @@ dependencies = [ "indexmap 2.9.0", "slab", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tracing", ] @@ -3370,7 +3542,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] @@ -3387,9 +3559,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -3409,11 +3581,11 @@ dependencies = [ [[package]] name = "headers" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", "headers-core", "http 1.3.1", @@ -3454,9 +3626,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3473,7 +3645,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", ] [[package]] @@ -3499,11 +3671,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3541,9 +3713,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.3.1", @@ -3551,22 +3723,22 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -3576,15 +3748,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -3613,9 +3785,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", + "h2 0.4.10", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -3627,16 +3799,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", "http 1.3.1", "hyper 1.6.0", "hyper-util", "rustls", - "rustls-native-certs 0.7.1", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -3674,33 +3845,41 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", + "windows-registry", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -3720,7 +3899,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1fcc7f316b2c079dde77564a1360639c1a956a23fa96122732e416cb10717bb" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "num-traits", "rand 0.8.5", "static_assertions", @@ -3728,21 +3907,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -3751,31 +3931,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -3783,67 +3943,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "id-arena" version = "2.2.1" @@ -3880,9 +4027,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -3917,13 +4064,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.102", ] [[package]] @@ -3944,32 +4091,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "serde", ] +[[package]] +name = "interprocess" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +dependencies = [ + "doctest-file", + "futures-core", + "libc", + "recvmsg", + "tokio", + "widestring", + "windows-sys 0.52.0", +] + [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -3991,9 +4163,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "ittapi" @@ -4015,12 +4187,37 @@ dependencies = [ "cc", ] +[[package]] +name = "jiff" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] @@ -4079,14 +4276,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3dc3e9cf2ba50b7b1d7d76a667619f82846caa39e8e8daa8a4962d74acaddca" dependencies = [ "anyhow", - "arrayvec 0.7.4", + "arrayvec 0.7.6", "async-trait", "beef", "futures-channel", "futures-util", "globset", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.32", "jsonrpsee-types", "lazy_static", "parking_lot", @@ -4094,7 +4291,7 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "serde_json", - "thiserror 1.0.61", + "thiserror 1.0.69", "tokio", "tracing", "unicase", @@ -4108,7 +4305,7 @@ checksum = "03802f0373a38c2420c70b5144742d800b509e2937edc4afb116434f07120117" dependencies = [ "futures-channel", "futures-util", - "hyper 0.14.29", + "hyper 0.14.32", "jsonrpsee-core", "jsonrpsee-types", "serde", @@ -4128,17 +4325,32 @@ dependencies = [ "beef", "serde", "serde_json", - "thiserror 1.0.61", + "thiserror 1.0.69", "tracing", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64 0.22.1", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "ecdsa", "elliptic-curve", "once_cell", @@ -4185,15 +4397,15 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25169bd5913a4b437588a7e3d127cd6e90127b60e0ffbd834a38f1599e016b8" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -4201,15 +4413,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" @@ -4219,15 +4431,15 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -4235,9 +4447,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lru" @@ -4245,9 +4457,15 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lru_time_cache" version = "0.11.11" @@ -4271,7 +4489,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -4310,15 +4528,15 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memfd" @@ -4326,7 +4544,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.34", + "rustix 0.38.44", ] [[package]] @@ -4368,22 +4586,22 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] @@ -4416,25 +4634,25 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.1" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" dependencies = [ "core2", - "unsigned-varint 0.7.2", + "unsigned-varint", ] [[package]] name = "multimap" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -4442,7 +4660,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.0", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4502,11 +4720,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", ] @@ -4527,7 +4745,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -4550,16 +4768,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "indexmap 2.9.0", "memchr", ] [[package]] name = "object_store" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ce831b09395f933addbc56d894d889e4b226eba304d4e7adbab591e26daf1e" +checksum = "7781f96d79ed0f961a7021424ab01840efbda64ae7a505aaea195efc91eaaec4" dependencies = [ "async-trait", "base64 0.22.1", @@ -4575,7 +4793,7 @@ dependencies = [ "parking_lot", "percent-encoding", "quick-xml", - "rand 0.8.5", + "rand 0.9.1", "reqwest", "ring", "rustls-pemfile", @@ -4587,6 +4805,8 @@ dependencies = [ "tracing", "url", "walkdir", + "wasm-bindgen-futures", + "web-time", ] [[package]] @@ -4595,6 +4815,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -4603,12 +4829,12 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.6.0", - "cfg-if 1.0.0", + "bitflags", + "cfg-if 1.0.1", "foreign-types", "libc", "once_cell", @@ -4624,20 +4850,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -4657,33 +4883,35 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width 0.1.13", + "unicode-width 0.1.14", ] [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bitvec", "byte-slice-cast", + "const_format", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.102", ] [[package]] @@ -4694,9 +4922,9 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -4704,13 +4932,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "libc", - "redox_syscall 0.5.2", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -4721,6 +4949,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64 0.22.1", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4729,20 +4967,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", - "thiserror 1.0.61", + "thiserror 2.0.12", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" dependencies = [ "pest", "pest_generator", @@ -4750,22 +4988,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", @@ -4784,59 +5022,69 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06" +checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" dependencies = [ "fixedbitset", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "indexmap 2.9.0", "serde", ] +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures 0.3.31", + "rustc_version 0.4.1", +] + [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -4856,9 +5104,24 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] [[package]] name = "postcard" @@ -4874,9 +5137,9 @@ dependencies = [ [[package]] name = "postgres" -version = "0.19.7" +version = "0.19.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7915b33ed60abc46040cbcaa25ffa1c7ec240668e0477c4f3070786f5916d451" +checksum = "363e6dfbdd780d3aa3597b6eb430db76bb315fa9bad7fae595bb8def808b8470" dependencies = [ "bytes", "fallible-iterator 0.2.0", @@ -4927,6 +5190,15 @@ dependencies = [ "postgres-protocol", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -4935,16 +5207,20 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "pq-sys" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24ff9e4cf6945c988f0db7005d87747bf72864965c3529d259ad155ac41d584" +checksum = "41c852911b98f5981956037b2ca976660612e548986c30af075e753107bc3400" dependencies = [ + "libc", "vcpkg", ] @@ -4960,12 +5236,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -4994,9 +5270,9 @@ dependencies = [ [[package]] name = "priority-queue" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef08705fa1589a1a59aa924ad77d14722cb0cd97b67dd5004ed5f4a4873fce8d" +checksum = "5676d703dda103cbb035b653a9f11448c0a7216c7926bd35fcb5865475d0c970" dependencies = [ "autocfg", "equivalent", @@ -5005,11 +5281,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -5031,7 +5307,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -5060,7 +5336,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "fnv", "lazy_static", "libc", @@ -5068,22 +5344,22 @@ dependencies = [ "parking_lot", "protobuf 2.28.0", "reqwest", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] name = "proptest" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.6.0", + "bitflags", "lazy_static", "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand 0.9.1", + "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -5117,7 +5393,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.101", + "syn 2.0.102", "tempfile", ] @@ -5131,7 +5407,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -5157,7 +5433,7 @@ checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" dependencies = [ "once_cell", "protobuf-support", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] @@ -5172,7 +5448,7 @@ dependencies = [ "protobuf 3.7.2", "protobuf-support", "tempfile", - "thiserror 1.0.61", + "thiserror 1.0.69", "which", ] @@ -5182,14 +5458,14 @@ version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" dependencies = [ - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" dependencies = [ "cc", ] @@ -5223,49 +5499,57 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", + "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 1.1.0", + "rustc-hash 2.1.1", "rustls", - "thiserror 1.0.61", + "socket2", + "thiserror 2.0.12", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "rand 0.8.5", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", "ring", "rustc-hash 2.1.1", "rustls", + "rustls-pki-types", "slab", - "thiserror 1.0.61", + "thiserror 2.0.12", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5277,6 +5561,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "r2d2" version = "0.8.10" @@ -5343,7 +5633,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -5352,17 +5642,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", "serde", ] [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.6.4", + "rand_core 0.9.3", ] [[package]] @@ -5385,6 +5675,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "recvmsg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" + [[package]] name = "redis" version = "0.31.0" @@ -5394,8 +5690,8 @@ dependencies = [ "arc-swap", "backon", "bytes", - "cfg-if 1.0.0", - "combine 4.6.7", + "cfg-if 1.0.1", + "combine", "futures-channel", "futures-util", "itoa", @@ -5406,37 +5702,39 @@ dependencies = [ "sha1_smol", "socket2", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "url", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] -name = "redox_syscall" -version = "0.5.2" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "bitflags 2.6.0", + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", - "thiserror 1.0.61", + "thiserror 2.0.12", ] [[package]] @@ -5447,7 +5745,7 @@ checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "log", "rustc-hash 2.1.1", "smallvec", @@ -5455,9 +5753,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -5467,9 +5765,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -5478,15 +5776,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" dependencies = [ "base64 0.22.1", "bytes", @@ -5494,45 +5792,41 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.5", + "h2 0.4.10", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "hyper 1.6.0", "hyper-rustls", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", "mime", "mime_guess", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", "rustls", - "rustls-native-certs 0.8.1", - "rustls-pemfile", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", + "sync_wrapper", "tokio", "tokio-native-tls", "tokio-rustls", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-http 0.6.6", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "windows-registry", ] [[package]] @@ -5547,13 +5841,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", - "getrandom 0.2.15", + "cfg-if 1.0.1", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -5571,9 +5865,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a46eb779843b2c4f21fac5773e25d6d5b7c8f0922876c91541790d2ca27eef" +checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -5604,9 +5898,9 @@ checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -5637,24 +5931,24 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.23", + "semver 1.0.26", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] @@ -5663,7 +5957,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys 0.9.4", @@ -5672,9 +5966,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.10" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "log", "once_cell", @@ -5685,19 +5979,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework 2.11.0", -] - [[package]] name = "rustls-native-certs" version = "0.8.1" @@ -5712,25 +5993,28 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -5739,9 +6023,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rusty-fork" @@ -5757,9 +6041,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -5772,11 +6056,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5850,11 +6134,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -5867,8 +6151,8 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "bitflags", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -5895,9 +6179,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] @@ -5911,6 +6195,12 @@ dependencies = [ "pest", ] +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.219" @@ -5928,25 +6218,26 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" dependencies = [ "itoa", "serde", @@ -5973,9 +6264,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -6006,40 +6297,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros 2.3.3", + "serde_with_macros", "time", ] -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros 3.12.0", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "serde_with_macros" version = "3.12.0" @@ -6049,7 +6310,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6082,7 +6343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -6094,7 +6355,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "cpufeatures", "digest 0.10.7", ] @@ -6107,11 +6368,11 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "cpufeatures", "digest 0.10.7", ] @@ -6133,14 +6394,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if 1.0.1", ] [[package]] name = "shellexpand" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ "dirs", ] @@ -6153,9 +6414,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -6170,11 +6431,23 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simple_asn1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.12", + "time", +] + [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -6255,18 +6528,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6334,15 +6607,15 @@ dependencies = [ [[package]] name = "stable-hash" version = "0.4.4" -source = "git+https://github.com/graphprotocol/stable-hash?branch=main#e50aabef55b8c4de581ca5c4ffa7ed8beed7e998" +source = "git+https://github.com/graphprotocol/stable-hash?branch=main#083b67b949eff48e210c5753eb9c777a73958d9b" dependencies = [ - "blake3 0.3.8", + "blake3 1.8.2", "firestorm 0.5.1", "ibig", "lazy_static", "leb128", "num-traits", - "uint 0.8.5", + "uint 0.10.0", "xxhash-rust", ] @@ -6409,7 +6682,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6422,7 +6695,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6445,7 +6718,7 @@ dependencies = [ "prost-build", "prost-types", "substreams-macro", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] @@ -6466,14 +6739,14 @@ version = "0.36.0" [[package]] name = "substreams-macro" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36f36e9da94db29f49daf3ab6b47b529b57c43fc5d58bc35b160aaad1a7233f" +checksum = "a3cf9954628fa6dee8458dade7088ce032e7f52267ef4777ad5bc2d1cfb4618a" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "thiserror 1.0.61", + "thiserror 1.0.69", ] [[package]] @@ -6483,7 +6756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ef8a763c5a5604b16f4898ab75d39494ef785c457aaca1fd7761b299f40fbf" dependencies = [ "bs58 0.4.0", - "getrandom 0.2.15", + "getrandom 0.2.16", "hex", "prost", "prost-build", @@ -6522,9 +6795,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" dependencies = [ "proc-macro2", "quote", @@ -6533,40 +6806,34 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0f0d4760f4c2a0823063b2c70e97aa2ad185f57be195172ccc0e23c4b787c4" +checksum = "14c8c8f496c33dc6343dac05b4be8d9e0bca180a4caa81d7b8416b10cc2273cd" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[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" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6575,7 +6842,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.6.0", + "bitflags", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6610,14 +6877,15 @@ checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if 1.0.0", "fastrand", - "rustix 0.38.34", - "windows-sys 0.52.0", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.7", + "windows-sys 0.59.0", ] [[package]] @@ -6642,12 +6910,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 0.38.34", - "windows-sys 0.48.0", + "rustix 1.0.7", + "windows-sys 0.59.0", ] [[package]] @@ -6670,11 +6938,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.61", + "thiserror-impl 1.0.69", ] [[package]] @@ -6688,13 +6956,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6705,7 +6973,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6714,7 +6982,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "once_cell", ] @@ -6729,9 +6997,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -6744,15 +7012,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -6778,9 +7046,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -6788,9 +7056,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -6827,7 +7095,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -6842,11 +7110,10 @@ dependencies = [ [[package]] name = "tokio-openssl" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffab79df67727f6acf57f1ff743091873c24c579b1e2ce4d8f53e47ded4d63d" +checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd" dependencies = [ - "futures-util", "openssl", "openssl-sys", "tokio", @@ -6874,7 +7141,7 @@ dependencies = [ "rand 0.9.1", "socket2", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "whoami", ] @@ -6891,12 +7158,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] @@ -6909,7 +7175,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", ] [[package]] @@ -6933,8 +7199,12 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", + "rustls", + "rustls-pki-types", "tokio", + "tokio-rustls", "tungstenite", + "webpki-roots 0.26.11", ] [[package]] @@ -6954,9 +7224,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -6968,48 +7238,44 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.16", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.9.0", + "serde", + "serde_spanned", "toml_datetime", - "winnow 0.5.40", + "toml_write", + "winnow", ] [[package]] -name = "toml_edit" -version = "0.22.16" +name = "toml_write" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" -dependencies = [ - "indexmap 2.9.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.13", -] +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tonic" @@ -7019,13 +7285,13 @@ checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.7.5", + "axum 0.7.9", "base64 0.22.1", "bytes", "flate2", - "h2 0.4.5", + "h2 0.4.10", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "hyper 1.6.0", "hyper-timeout", @@ -7033,7 +7299,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "rustls-native-certs 0.8.1", + "rustls-native-certs", "rustls-pemfile", "socket2", "tokio", @@ -7056,7 +7322,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -7073,7 +7339,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -7088,7 +7354,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.1", + "sync_wrapper", "tokio", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7098,7 +7364,7 @@ dependencies = [ [[package]] name = "tower" version = "0.5.2" -source = "git+https://github.com/tower-rs/tower.git#abb375d08cf0ba34c1fe76f66f1aba3dc4341013" +source = "git+https://github.com/tower-rs/tower.git#ec81e5797bb80ea7b65d243312db6ec2fdb6ce0e" dependencies = [ "futures-core", "futures-util", @@ -7106,9 +7372,9 @@ dependencies = [ "indexmap 2.9.0", "pin-project-lite", "slab", - "sync_wrapper 1.0.1", + "sync_wrapper", "tokio", - "tokio-util 0.7.11", + "tokio-util 0.7.15", "tower-layer 0.3.3 (git+https://github.com/tower-rs/tower.git)", "tower-service 0.3.3 (git+https://github.com/tower-rs/tower.git)", "tracing", @@ -7120,16 +7386,34 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.6.0", + "bitflags", "bytes", "http 1.3.1", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "pin-project-lite", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -7139,7 +7423,7 @@ checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-layer" version = "0.3.3" -source = "git+https://github.com/tower-rs/tower.git#abb375d08cf0ba34c1fe76f66f1aba3dc4341013" +source = "git+https://github.com/tower-rs/tower.git#ec81e5797bb80ea7b65d243312db6ec2fdb6ce0e" [[package]] name = "tower-service" @@ -7150,14 +7434,13 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tower-service" version = "0.3.3" -source = "git+https://github.com/tower-rs/tower.git#abb375d08cf0ba34c1fe76f66f1aba3dc4341013" +source = "git+https://github.com/tower-rs/tower.git#ec81e5797bb80ea7b65d243312db6ec2fdb6ce0e" [[package]] name = "tower-test" version = "0.4.1" -source = "git+https://github.com/tower-rs/tower.git#abb375d08cf0ba34c1fe76f66f1aba3dc4341013" +source = "git+https://github.com/tower-rs/tower.git#ec81e5797bb80ea7b65d243312db6ec2fdb6ce0e" dependencies = [ - "futures-util", "pin-project-lite", "tokio", "tokio-test", @@ -7167,9 +7450,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -7179,20 +7462,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] @@ -7203,7 +7486,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "futures-task", "pin-project", "tracing", @@ -7217,7 +7500,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -7245,6 +7528,8 @@ dependencies = [ "httparse", "log", "rand 0.9.1", + "rustls", + "rustls-pki-types", "sha1", "thiserror 2.0.12", "utf-8", @@ -7252,33 +7537,33 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" -version = "0.8.5" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", - "rustc-hex", + "hex", "static_assertions", ] [[package]] name = "uint" -version = "0.9.5" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" dependencies = [ "byteorder", "crunchy", @@ -7294,39 +7579,36 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-segmentation" @@ -7336,30 +7618,21 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unreachable" -version = "1.0.0" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unsafe-libyaml" @@ -7367,12 +7640,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "unsigned-varint" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" - [[package]] name = "unsigned-varint" version = "0.8.0" @@ -7402,12 +7669,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -7422,9 +7683,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "valuable" @@ -7440,15 +7705,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -7480,15 +7739,15 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -7505,7 +7764,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -7521,18 +7780,19 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] @@ -7555,7 +7815,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7581,12 +7841,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.233.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9679ae3cf7cfa2ca3a327f7fab97f27f3294d402fd1a76ca8ab514e17973e4d3" +checksum = "170a0157eef517a179f2d20ed7c68df9c3f7f6c1c047782d488bf5a464174684" dependencies = [ "leb128fmt", - "wasmparser 0.233.0", + "wasmparser 0.234.0", ] [[package]] @@ -7600,9 +7860,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -7618,7 +7878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" dependencies = [ "indexmap 2.9.0", - "semver 1.0.23", + "semver 1.0.26", ] [[package]] @@ -7627,22 +7887,22 @@ version = "0.229.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc3b1f053f5d41aa55640a1fa9b6d1b8a9e4418d118ce308d20e24ff3575a8c" dependencies = [ - "bitflags 2.6.0", - "hashbrown 0.15.2", + "bitflags", + "hashbrown 0.15.4", "indexmap 2.9.0", - "semver 1.0.23", + "semver 1.0.26", "serde", ] [[package]] name = "wasmparser" -version = "0.233.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51cb03afce7964bbfce46602d6cb358726f36430b6ba084ac6020d8ce5bc102" +checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5" dependencies = [ - "bitflags 2.6.0", + "bitflags", "indexmap 2.9.0", - "semver 1.0.23", + "semver 1.0.26", ] [[package]] @@ -7662,17 +7922,17 @@ version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15396de4fce22e431aa913a9d17325665e72a39aaa7972c8aeae7507eff6144f" dependencies = [ - "addr2line 0.24.2", + "addr2line", "anyhow", "async-trait", - "bitflags 2.6.0", + "bitflags", "bumpalo", "cc", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "encoding_rs", "fxprof-processed-profile", - "gimli 0.31.1", - "hashbrown 0.15.2", + "gimli", + "hashbrown 0.15.4", "indexmap 2.9.0", "ittapi", "libc", @@ -7686,7 +7946,7 @@ dependencies = [ "pulley-interpreter", "rayon", "rustix 1.0.7", - "semver 1.0.23", + "semver 1.0.26", "serde", "serde_derive", "serde_json", @@ -7719,7 +7979,7 @@ version = "33.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d13b1a25d9b77ce42b4641a797e8c0bde0643b9ad5aaa36ce7e00cf373ffab" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", ] [[package]] @@ -7751,7 +8011,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasmtime-component-util", "wasmtime-wit-bindgen", "wit-parser", @@ -7770,13 +8030,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c2c2e083dc4c119cca61cc42ca6b3711b75ed9823f77b684ee009c74f939d8" dependencies = [ "anyhow", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "cranelift-codegen", "cranelift-control", "cranelift-entity", "cranelift-frontend", "cranelift-native", - "gimli 0.31.1", + "gimli", "itertools 0.14.0", "log", "object", @@ -7799,13 +8059,13 @@ dependencies = [ "cpp_demangle", "cranelift-bitset", "cranelift-entity", - "gimli 0.31.1", + "gimli", "indexmap 2.9.0", "log", "object", "postcard", "rustc-demangle", - "semver 1.0.23", + "semver 1.0.26", "serde", "serde_derive", "smallvec", @@ -7824,7 +8084,7 @@ checksum = "d83e697b13d6ae9eff31edac86673aabaf8dbf20267f2aa20e831dd01da480a3" dependencies = [ "anyhow", "cc", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "rustix 1.0.7", "wasmtime-asm-macros", "wasmtime-versioned-export-macros", @@ -7850,7 +8110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175e924dbc944c185808466d1e90b5a7feb610f3b9abdfe26f8ee25fd1086d1c" dependencies = [ "anyhow", - "cfg-if 1.0.0", + "cfg-if 1.0.1", "libc", "windows-sys 0.59.0", ] @@ -7878,7 +8138,7 @@ checksum = "55b39ffeda28be925babb2d45067d8ba2c67d2227328c5364d23b4152eba9950" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -7889,7 +8149,7 @@ checksum = "1f180e6a8c0724608cd2d55ceb7d03ed3a729ca78fcd34a6756f36cf9a5fd546" dependencies = [ "anyhow", "cranelift-codegen", - "gimli 0.31.1", + "gimli", "object", "target-lexicon", "wasmparser 0.229.0", @@ -7926,31 +8186,41 @@ dependencies = [ [[package]] name = "wast" -version = "233.0.0" +version = "234.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eaf4099d8d0c922b83bf3c90663f5666f0769db9e525184284ebbbdb1dd2180" +checksum = "f5fc6bea84cc3007ad3e68c6223f52095e6093eec4d7ebdff355f2c952fd9007" dependencies = [ "bumpalo", "leb128fmt", "memchr", - "unicode-width 0.2.0", - "wasm-encoder 0.233.0", + "unicode-width 0.2.1", + "wasm-encoder 0.234.0", ] [[package]] name = "wat" -version = "1.233.0" +version = "1.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d9bc80f5e4b25ea086ef41b91ccd244adde45d931c384d94a8ff64ab8bd7d87" +checksum = "1a4807d67cf6885965d2f118744fd0ad20ffb9082c875de532af37b499e65aa6" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -7961,10 +8231,10 @@ name = "web3" version = "0.19.0-graph" source = "git+https://github.com/graphprotocol/rust-web3?branch=graph-patches-onto-0.18#f9f27f45ce23bf489d8bd010b50b2b207eb316cb" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "base64 0.13.1", "bytes", - "derive_more 0.99.19", + "derive_more 0.99.20", "ethabi", "ethereum-types", "futures 0.3.31", @@ -7998,11 +8268,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" dependencies = [ "native-tls", - "thiserror 1.0.61", + "thiserror 1.0.69", "tokio", "url", ] +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" @@ -8012,20 +8300,26 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.34", + "rustix 0.38.44", ] [[package]] name = "whoami" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall", "wasite", "web-sys", ] +[[package]] +name = "widestring" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" + [[package]] name = "winapi" version = "0.3.9" @@ -8044,11 +8338,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8066,7 +8360,7 @@ dependencies = [ "anyhow", "cranelift-assembler-x64", "cranelift-codegen", - "gimli 0.31.1", + "gimli", "regalloc2", "smallvec", "target-lexicon", @@ -8078,57 +8372,74 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", ] [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "d3bfe459f85da17560875b8bf1423d6f113b7a87a5d942e7da0ac71be7c61f8b" [[package]] name = "windows-registry" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" dependencies = [ + "windows-link", "windows-result", "windows-strings", - "windows-targets 0.53.0", ] [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -8148,18 +8459,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.60.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "b36e9ed89376c545e20cbf5a13c306b49106b21b9d1d4f9cb9a1cb6b1e9ee06a" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets 0.53.1", ] [[package]] @@ -8180,9 +8485,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "30357ec391cde730f8fbfcdc29adc47518b06504528df977ab5af02ef23fdee9" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", @@ -8194,12 +8499,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -8212,12 +8511,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -8230,12 +8523,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -8260,12 +8547,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -8278,12 +8559,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -8296,12 +8571,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -8314,12 +8583,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -8334,27 +8597,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.7.9" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -8385,11 +8630,11 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -8402,7 +8647,7 @@ dependencies = [ "id-arena", "indexmap 2.9.0", "log", - "semver 1.0.23", + "semver 1.0.26", "serde", "serde_derive", "serde_json", @@ -8411,16 +8656,29 @@ dependencies = [ ] [[package]] -name = "write16" -version = "1.0.0" +name = "writeable" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] -name = "writeable" -version = "0.5.5" +name = "ws_stream_wasm" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "6c173014acad22e83f16403ee360115b38846fe754e735c5d9d3803fe70c6abc" +dependencies = [ + "async_io_stream", + "futures 0.3.31", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.1", + "send_wrapper", + "thiserror 2.0.12", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] [[package]] name = "wyz" @@ -8433,9 +8691,9 @@ dependencies = [ [[package]] name = "xxhash-rust" -version = "0.8.11" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63658493314859b4dfdf3fb8c1defd61587839def09582db50b8a4e93afca6bb" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yansi" @@ -8445,9 +8703,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -8457,16 +8715,36 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "zerofrom" version = "0.1.6" @@ -8484,7 +8762,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "synstructure", ] @@ -8505,14 +8783,25 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", ] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -8521,13 +8810,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2d5805eeacc..ab953c993a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,8 @@ repository = "https://github.com/graphprotocol/graph-node" license = "MIT OR Apache-2.0" [workspace.dependencies] -alloy = { version = "0.15.10", features = ["dyn-abi", "json-abi"] } +alloy = { version = "0.15.10", features = ["full"] } +alloy-rpc-types = "0.15.10" anyhow = "1.0" async-graphql = { version = "7.0.15", features = ["chrono"] } async-graphql-axum = "7.0.15" diff --git a/chain/ethereum/Cargo.toml b/chain/ethereum/Cargo.toml index 04cd034e184..5193fa31fb6 100644 --- a/chain/ethereum/Cargo.toml +++ b/chain/ethereum/Cargo.toml @@ -4,6 +4,8 @@ version.workspace = true edition.workspace = true [dependencies] +alloy.workspace = true +alloy-rpc-types.workspace = true envconfig = "0.11.0" jsonrpc-core = "18.0.0" graph = { path = "../../graph" } From 4211416326b3eedbf5fd4426a77f84eb2172ef81 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 18:13:21 +0530 Subject: [PATCH 04/44] chain/ethereum: Add alloy provider to ethereum adapter --- chain/ethereum/src/ethereum_adapter.rs | 33 +++++++++++++++++++++++++- chain/ethereum/src/transport.rs | 7 ++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 8ee2386b44d..d277bdb9a82 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1,3 +1,5 @@ +use alloy::primitives::B256; +use alloy::providers::{Provider, ProviderBuilder}; use futures03::{future::BoxFuture, stream::FuturesUnordered}; use graph::abi; use graph::abi::DynSolValueExt; @@ -72,23 +74,40 @@ use crate::{ ENV_VARS, }; -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct EthereumAdapter { logger: Logger, provider: String, web3: Arc>, + alloy: Arc, metrics: Arc, supports_eip_1898: bool, call_only: bool, supports_block_receipts: Arc>>, } +impl std::fmt::Debug for EthereumAdapter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EthereumAdapter") + .field("logger", &self.logger) + .field("provider", &self.provider) + .field("web3", &self.web3) + .field("alloy", &"") + .field("metrics", &self.metrics) + .field("supports_eip_1898", &self.supports_eip_1898) + .field("call_only", &self.call_only) + .field("supports_block_receipts", &self.supports_block_receipts) + .finish() + } +} + impl CheapClone for EthereumAdapter { fn cheap_clone(&self) -> Self { Self { logger: self.logger.clone(), provider: self.provider.clone(), web3: self.web3.cheap_clone(), + alloy: self.alloy.clone(), metrics: self.metrics.cheap_clone(), supports_eip_1898: self.supports_eip_1898, call_only: self.call_only, @@ -110,12 +129,24 @@ impl EthereumAdapter { supports_eip_1898: bool, call_only: bool, ) -> Self { + let rpc_url = match &transport { + Transport::RPC { + client: _, + metrics: _, + provider: _, + rpc_url, + } => rpc_url.clone(), + Transport::IPC(_ipc) => todo!(), + Transport::WS(_web_socket) => todo!(), + }; let web3 = Arc::new(Web3::new(transport)); + let alloy = Arc::new(ProviderBuilder::new().connect(&rpc_url).await.unwrap()); EthereumAdapter { logger, provider, web3, + alloy, metrics: provider_metrics, supports_eip_1898, call_only, diff --git a/chain/ethereum/src/transport.rs b/chain/ethereum/src/transport.rs index a90a6b9720b..740f46044a8 100644 --- a/chain/ethereum/src/transport.rs +++ b/chain/ethereum/src/transport.rs @@ -17,6 +17,7 @@ pub enum Transport { client: http::Http, metrics: Arc, provider: ProviderName, + url: String, }, IPC(ipc::Ipc), WS(ws::WebSocket), @@ -56,10 +57,13 @@ impl Transport { .build() .unwrap(); + let rpc_url = rpc.to_string(); + Transport::RPC { client: http::Http::with_client(client, rpc), metrics, provider: provider.as_ref().into(), + url: rpc_url, } } } @@ -73,6 +77,7 @@ impl web3::Transport for Transport { client, metrics: _, provider: _, + url: _, } => client.prepare(method, params), Transport::IPC(ipc) => ipc.prepare(method, params), Transport::WS(ws) => ws.prepare(method, params), @@ -85,6 +90,7 @@ impl web3::Transport for Transport { client, metrics, provider, + url: _, } => { let metrics = metrics.cheap_clone(); let client = client.clone(); @@ -132,6 +138,7 @@ impl web3::BatchTransport for Transport { client, metrics: _, provider: _, + url: _, } => Box::new(client.send_batch(requests)), Transport::IPC(ipc) => Box::new(ipc.send_batch(requests)), Transport::WS(ws) => Box::new(ws.send_batch(requests)), From 92265014b5ac6b1aed38d225a68ac1fe51123b86 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 18:19:56 +0530 Subject: [PATCH 05/44] chain/ethereum: Fix retval import causing rustfmt issues --- chain/ethereum/src/ethereum_adapter.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index d277bdb9a82..94ebad665fd 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1635,9 +1635,8 @@ impl EthereumAdapterTrait for EthereumAdapter { source, req: _, } = resp; - use call::Retval::*; match retval { - Value(output) => match call.function.abi_decode_output(&output) { + call::Retval::Value(output) => match call.function.abi_decode_output(&output) { Ok(tokens) => (Some(tokens), source), Err(e) => { // Decode failures are reverts. The reasoning is that if Solidity fails to @@ -1647,7 +1646,7 @@ impl EthereumAdapterTrait for EthereumAdapter { (None, call::Source::Rpc) } }, - Null => { + call::Retval::Null => { // We got a `0x` response. For old Geth, this can mean a revert. It can also be // that the contract actually returned an empty response. A view call is meant // to return something, so we treat empty responses the same as reverts. From cf1b8754f31d845811eb80644180f7853472f7dd Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 18:44:10 +0530 Subject: [PATCH 06/44] chain/ethereum: migrate get_balance call to use alloy --- chain/ethereum/src/adapter.rs | 9 ++++-- chain/ethereum/src/ethereum_adapter.rs | 30 +++++++++++-------- chain/ethereum/src/runtime/runtime_adapter.rs | 6 ++-- graph/src/data/store/scalar/bigint.rs | 6 ++++ runtime/wasm/Cargo.toml | 1 + runtime/wasm/src/to_from/external.rs | 22 ++++++++++++++ 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 47ea9950e3d..30930eed0bd 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1,3 +1,5 @@ +use alloy::transports::RpcError; +use alloy::transports::TransportErrorKind; use anyhow::Error; use graph::abi; use graph::blockchain::ChainIdentifier; @@ -9,7 +11,6 @@ use graph::firehose::CombinedFilter; use graph::firehose::LogFilter; use graph::prelude::web3::types::Bytes; use graph::prelude::web3::types::H160; -use graph::prelude::web3::types::U256; use itertools::Itertools; use prost::Message; use prost_types::Any; @@ -95,6 +96,8 @@ impl EventSignatureWithTopics { pub enum EthereumRpcError { #[error("call error: {0}")] Web3Error(web3::Error), + #[error("call error: {0}")] + AlloyError(RpcError), #[error("ethereum node took too long to perform call")] Timeout, } @@ -1171,9 +1174,9 @@ pub trait EthereumAdapter: Send + Sync + 'static { async fn get_balance( &self, logger: &Logger, - address: H160, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result; + ) -> Result; // Returns the compiled bytecode of a smart contract async fn get_code( diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 94ebad665fd..be6c4c8d504 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -22,7 +22,6 @@ use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; use graph::prelude::tokio::try_join; -use graph::prelude::web3::types::U256; use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; @@ -134,7 +133,7 @@ impl EthereumAdapter { client: _, metrics: _, provider: _, - rpc_url, + url: rpc_url, } => rpc_url.clone(), Transport::IPC(_ipc) => todo!(), Transport::WS(_web_socket) => todo!(), @@ -521,6 +520,14 @@ impl EthereumAdapter { } } + fn block_ptr_to_alloy_block_id(&self, block_ptr: &BlockPtr) -> alloy_rpc_types::BlockId { + if !self.supports_eip_1898 { + alloy_rpc_types::BlockId::number(block_ptr.number as u64) + } else { + alloy_rpc_types::BlockId::hash(B256::new(*block_ptr.hash_as_h256().as_fixed_bytes())) + } + } + async fn code( &self, logger: &Logger, @@ -559,13 +566,13 @@ impl EthereumAdapter { async fn balance( &self, logger: &Logger, - address: Address, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result { - let web3 = self.web3.clone(); + ) -> Result { + let alloy = self.alloy.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); - let block_id = self.block_ptr_to_id(&block_ptr); + let block_id = self.block_ptr_to_alloy_block_id(&block_ptr); let retry_log_message = format!("eth_getBalance RPC call for block {}", block_ptr); retry(retry_log_message, &logger) @@ -577,13 +584,12 @@ impl EthereumAdapter { .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - let result: Result = - web3.eth().balance(address, Some(block_id)).boxed().await; + let result = alloy.get_balance(address).block_id(block_id).await; match result { Ok(balance) => Ok(balance), - Err(err) => Err(EthereumRpcError::Web3Error(err)), + Err(err) => Err(EthereumRpcError::AlloyError(err)), } } }) @@ -1493,9 +1499,9 @@ impl EthereumAdapterTrait for EthereumAdapter { async fn get_balance( &self, logger: &Logger, - address: H160, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result { + ) -> Result { debug!( logger, "eth_getBalance"; "address" => format!("{}", address), diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index 91f7e2dd1a4..3380bb789b2 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -224,17 +224,18 @@ fn eth_get_balance( let logger = &ctx.logger; let block_ptr = &ctx.block_ptr; - let address: H160 = asc_get(ctx.heap, wasm_ptr.into(), &ctx.gas, 0)?; + let address: alloy::primitives::Address = asc_get(ctx.heap, wasm_ptr.into(), &ctx.gas, 0)?; let result = graph::block_on(eth_adapter.get_balance(logger, address, block_ptr.clone())); match result { Ok(v) => { - let bigint = BigInt::from_unsigned_u256(&v); + let bigint = BigInt::from_unsigned_alloy_u256(&v); Ok(asc_new(ctx.heap, &bigint, &ctx.gas)?) } // Retry on any kind of error Err(EthereumRpcError::Web3Error(e)) => Err(HostExportError::PossibleReorg(e.into())), + Err(EthereumRpcError::AlloyError(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::Timeout) => Err(HostExportError::PossibleReorg( EthereumRpcError::Timeout.into(), )), @@ -267,6 +268,7 @@ fn eth_has_code( Ok(v) => Ok(asc_new(ctx.heap, &AscWrapped { inner: v }, &ctx.gas)?), // Retry on any kind of error Err(EthereumRpcError::Web3Error(e)) => Err(HostExportError::PossibleReorg(e.into())), + Err(EthereumRpcError::AlloyError(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::Timeout) => Err(HostExportError::PossibleReorg( EthereumRpcError::Timeout.into(), )), diff --git a/graph/src/data/store/scalar/bigint.rs b/graph/src/data/store/scalar/bigint.rs index c344ec83a6d..3d46fb2b861 100644 --- a/graph/src/data/store/scalar/bigint.rs +++ b/graph/src/data/store/scalar/bigint.rs @@ -186,6 +186,12 @@ impl BigInt { BigInt::from_unsigned_bytes_le(&bytes).unwrap() } + pub fn from_unsigned_alloy_u256(n: &alloy::primitives::U256) -> Self { + let bytes = n.to_le_bytes_trimmed_vec(); + // Unwrap: 256 bits is much less than BigInt::MAX_BITS + BigInt::from_unsigned_bytes_le(&bytes).unwrap() + } + pub fn from_signed_u256(n: &U256) -> Self { let mut bytes: [u8; 32] = [0; 32]; n.to_little_endian(&mut bytes); diff --git a/runtime/wasm/Cargo.toml b/runtime/wasm/Cargo.toml index 2ca24759d0d..5c2bd2fe06b 100644 --- a/runtime/wasm/Cargo.toml +++ b/runtime/wasm/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +alloy = { workspace = true } async-trait = "0.1.50" hex = "0.4.3" graph = { path = "../../graph" } diff --git a/runtime/wasm/src/to_from/external.rs b/runtime/wasm/src/to_from/external.rs index 85074f492ca..fcfde250853 100644 --- a/runtime/wasm/src/to_from/external.rs +++ b/runtime/wasm/src/to_from/external.rs @@ -46,6 +46,28 @@ impl FromAscObj for web3::H160 { } } +impl FromAscObj for alloy::primitives::Address { + fn from_asc_obj( + typed_array: Uint8Array, + heap: &H, + gas: &GasCounter, + depth: usize, + ) -> Result { + let data = <[u8; 20]>::from_asc_obj(typed_array, heap, gas, depth)?; + Ok(Self::from(data)) + } +} + +impl ToAscObj for alloy::primitives::Address { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + self.as_slice().to_asc_obj(heap, gas) + } +} + impl FromAscObj for web3::H256 { fn from_asc_obj( typed_array: Uint8Array, From d592accc2bf333882f7fd818bbd9ca4e42266feb Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 18:55:08 +0530 Subject: [PATCH 07/44] chain/ethereum: migrate get_code call to use alloy --- chain/ethereum/src/adapter.rs | 5 ++-- chain/ethereum/src/ethereum_adapter.rs | 23 +++++++++---------- chain/ethereum/src/runtime/runtime_adapter.rs | 5 ++-- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 30930eed0bd..9f60a535fba 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -9,7 +9,6 @@ use graph::data_source::common::ContractCall; use graph::firehose::CallToFilter; use graph::firehose::CombinedFilter; use graph::firehose::LogFilter; -use graph::prelude::web3::types::Bytes; use graph::prelude::web3::types::H160; use itertools::Itertools; use prost::Message; @@ -1182,9 +1181,9 @@ pub trait EthereumAdapter: Send + Sync + 'static { async fn get_code( &self, logger: &Logger, - address: H160, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result; + ) -> Result; } #[cfg(test)] diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index be6c4c8d504..f9172d03f4d 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -33,8 +33,8 @@ use graph::{ web3::{ self, types::{ - Address, BlockId, BlockNumber as Web3BlockNumber, Bytes, CallRequest, Filter, - FilterBuilder, Log, Transaction, TransactionReceipt, H256, + BlockId, BlockNumber as Web3BlockNumber, Bytes, CallRequest, Filter, FilterBuilder, + Log, Transaction, TransactionReceipt, H256, }, }, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, @@ -531,13 +531,13 @@ impl EthereumAdapter { async fn code( &self, logger: &Logger, - address: Address, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result { - let web3 = self.web3.clone(); + ) -> Result { + let alloy = self.alloy.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); - let block_id = self.block_ptr_to_id(&block_ptr); + let block_id = self.block_ptr_to_alloy_block_id(&block_ptr); let retry_log_message = format!("eth_getCode RPC call for block {}", block_ptr); retry(retry_log_message, &logger) @@ -549,13 +549,12 @@ impl EthereumAdapter { .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - let result: Result = - web3.eth().code(address, Some(block_id)).boxed().await; + let result = alloy.get_code_at(address).block_id(block_id).await; match result { Ok(code) => Ok(code), - Err(err) => Err(EthereumRpcError::Web3Error(err)), + Err(err) => Err(EthereumRpcError::AlloyError(err)), } } }) @@ -1513,9 +1512,9 @@ impl EthereumAdapterTrait for EthereumAdapter { async fn get_code( &self, logger: &Logger, - address: H160, + address: alloy::primitives::Address, block_ptr: BlockPtr, - ) -> Result { + ) -> Result { debug!( logger, "eth_getCode"; "address" => format!("{}", address), diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index 3380bb789b2..ad635e81314 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -17,7 +17,6 @@ use graph::data::subgraph::API_VERSION_0_0_9; use graph::data_source; use graph::data_source::common::{ContractCall, MappingABI}; use graph::prelude::web3::types::Address; -use graph::prelude::web3::types::H160; use graph::runtime::gas::Gas; use graph::runtime::{AscIndexId, IndexForAscTypeId}; use graph::slog::debug; @@ -259,10 +258,10 @@ fn eth_has_code( let logger = &ctx.logger; let block_ptr = &ctx.block_ptr; - let address: H160 = asc_get(ctx.heap, wasm_ptr.into(), &ctx.gas, 0)?; + let address: alloy::primitives::Address = asc_get(ctx.heap, wasm_ptr.into(), &ctx.gas, 0)?; let result = graph::block_on(eth_adapter.get_code(logger, address, block_ptr.clone())) - .map(|v| !v.0.is_empty()); + .map(|v| !v.is_empty()); match result { Ok(v) => Ok(asc_new(ctx.heap, &AscWrapped { inner: v }, &ctx.gas)?), From 3035f4e9b1c19e7328c6728cdc8a6f82eed5ec9d Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:03:17 +0530 Subject: [PATCH 08/44] chain/ethereum: remove unused block_hash_by_block_number method --- chain/ethereum/src/adapter.rs | 15 ----------- chain/ethereum/src/ethereum_adapter.rs | 35 -------------------------- 2 files changed, 50 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 9f60a535fba..477276ba7b9 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1124,21 +1124,6 @@ pub trait EthereumAdapter: Send + Sync + 'static { block: LightEthereumBlock, ) -> Result; - /// Find a block by its number, according to the Ethereum node. - /// - /// Careful: don't use this function without considering race conditions. - /// Chain reorgs could happen at any time, and could affect the answer received. - /// Generally, it is only safe to use this function with blocks that have received enough - /// confirmations to guarantee no further reorgs, **and** where the Ethereum node is aware of - /// those confirmations. - /// If the Ethereum node is far behind in processing blocks, even old blocks can be subject to - /// reorgs. - async fn block_hash_by_block_number( - &self, - logger: &Logger, - block_number: BlockNumber, - ) -> Result, Error>; - /// Finds the hash and number of the lowest non-null block with height greater than or equal to /// the given number. /// diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index f9172d03f4d..a3accbb00e9 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1460,41 +1460,6 @@ impl EthereumAdapterTrait for EthereumAdapter { }) } - async fn block_hash_by_block_number( - &self, - logger: &Logger, - block_number: BlockNumber, - ) -> Result, Error> { - let web3 = self.web3.clone(); - let retry_log_message = format!( - "eth_getBlockByNumber RPC call for block number {}", - block_number - ); - retry(retry_log_message, logger) - .redact_log_urls(true) - .no_limit() - .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || { - let web3 = web3.cheap_clone(); - async move { - web3.eth() - .block(BlockId::Number(block_number.into())) - .await - .map(|block_opt| block_opt.and_then(|block| block.hash)) - .map_err(Error::from) - } - }) - .await - .map_err(move |e| { - e.into_inner().unwrap_or_else(move || { - anyhow!( - "Ethereum node took too long to return data for block #{}", - block_number - ) - }) - }) - } - async fn get_balance( &self, logger: &Logger, From 3327f3c3e98182f025ae3bed1ffb4b33ab6583b1 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:16:19 +0530 Subject: [PATCH 09/44] chain/ethereum: migrate chain_id call to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index a3accbb00e9..a8da7174c9a 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1170,19 +1170,17 @@ impl EthereumAdapter { pub async fn chain_id(&self) -> Result { let logger = self.logger.clone(); - let web3 = self.web3.clone(); - u64::try_from( - retry("chain_id RPC call", &logger) - .redact_log_urls(true) - .no_limit() - .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || { - let web3 = web3.cheap_clone(); - async move { web3.eth().chain_id().await } - }) - .await?, - ) - .map_err(Error::msg) + let alloy = self.alloy.clone(); + retry("chain_id RPC call", &logger) + .redact_log_urls(true) + .no_limit() + .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) + .run(move || { + let alloy = alloy.cheap_clone(); + async move { alloy.get_chain_id().await.map_err(Error::from) } + }) + .await + .map_err(|e| e.into_inner().unwrap_or(EthereumRpcError::Timeout.into())) } } From 004f986d17871ac19de5bac95157697d2878c24e Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:22:12 +0530 Subject: [PATCH 10/44] chain/ethereum: migrate net_version call to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index a8da7174c9a..92b657211cb 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1203,7 +1203,7 @@ impl EthereumAdapterTrait for EthereumAdapter { async fn net_identifiers(&self) -> Result { let logger = self.logger.clone(); - let web3 = self.web3.clone(); + let alloy = self.alloy.clone(); let metrics = self.metrics.clone(); let provider = self.provider().to_string(); let net_version_future = retry("net_version RPC call", &logger) @@ -1211,11 +1211,11 @@ impl EthereumAdapterTrait for EthereumAdapter { .no_limit() .timeout_secs(20) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); let metrics = metrics.cheap_clone(); let provider = provider.clone(); async move { - web3.net().version().await.map_err(|e| { + alloy.get_net_version().await.map_err(|e| { metrics.set_status(ProviderStatus::VersionFail, &provider); e.into() }) @@ -1272,7 +1272,7 @@ impl EthereumAdapterTrait for EthereumAdapter { })?; let ident = ChainIdentifier { - net_version, + net_version: net_version.to_string(), genesis_block_hash, }; From ed10f44da8b1b8e8161fabd3cda085786fa790b8 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:33:59 +0530 Subject: [PATCH 11/44] chain/ethereum: migrate next_existing_ptr_to_number call to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 92b657211cb..fec450f050a 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1497,7 +1497,7 @@ impl EthereumAdapterTrait for EthereumAdapter { "eth_getBlockByNumber RPC call for block number {}", next_number ); - let web3 = self.web3.clone(); + let alloy = self.alloy.clone(); let logger = logger.clone(); let res = retry(retry_log_message, &logger) .redact_log_urls(true) @@ -1505,12 +1505,16 @@ impl EthereumAdapterTrait for EthereumAdapter { .no_limit() .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - web3.eth() - .block(BlockId::Number(next_number.into())) + alloy + .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + next_number as u64, + )) .await - .map(|block_opt| block_opt.and_then(|block| block.hash)) + .map(|block_opt| { + block_opt.map(|block| BlockHash::from(block.header.hash.0.to_vec())) + }) .map_err(Error::from) } }) @@ -1528,7 +1532,7 @@ impl EthereumAdapterTrait for EthereumAdapter { continue; } return match res { - Ok(Some(hash)) => Ok(BlockPtr::new(hash.into(), next_number)), + Ok(Some(hash)) => Ok(BlockPtr::new(hash, next_number)), Ok(None) => Err(anyhow!("Block {} does not contain hash", next_number)), Err(e) => Err(e), }; From 8d432a638687ed986ed0711071b9905973e6f237 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:48:18 +0530 Subject: [PATCH 12/44] chain/ethereum: migrate load_block_ptrs_by_numbers_rpc call to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 21 ++++++++++--------- graph/src/blockchain/types.rs | 28 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index fec450f050a..8d0b3e054dc 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -822,10 +822,10 @@ impl EthereumAdapter { logger: Logger, numbers: Vec, ) -> impl futures03::Stream, Error>> + Send { - let web3 = self.web3.clone(); + let alloy = self.alloy.clone(); futures03::stream::iter(numbers.into_iter().map(move |number| { - let web3 = web3.clone(); + let alloy = alloy.clone(); let logger = logger.clone(); async move { @@ -834,21 +834,22 @@ impl EthereumAdapter { .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.clone(); + let alloy = alloy.cheap_clone(); async move { - let block_result = web3 - .eth() - .block(BlockId::Number(Web3BlockNumber::Number(number.into()))) + let block_result = alloy + .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + number as u64, + )) .await; match block_result { Ok(Some(block)) => { let ptr = ExtendedBlockPtr::try_from(( - block.hash, - block.number, - block.parent_hash, - block.timestamp, + block.header.hash, + block.header.number as i32, + block.header.parent_hash, + block.header.timestamp, )) .map_err(|e| { anyhow::anyhow!("Failed to convert block: {}", e) diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index 081fff4eea5..7ce9b4dcf18 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -95,6 +95,12 @@ impl From> for BlockHash { } } +impl From for BlockHash { + fn from(hash: alloy::primitives::B256) -> Self { + BlockHash(hash.0.to_vec().into()) + } +} + impl TryFrom<&str> for BlockHash { type Error = anyhow::Error; @@ -510,6 +516,28 @@ impl TryFrom<(H256, i32, H256, U256)> for ExtendedBlockPtr { }) } } + +impl TryFrom<(alloy::primitives::B256, i32, alloy::primitives::B256, u64)> for ExtendedBlockPtr { + type Error = anyhow::Error; + + fn try_from( + tuple: (alloy::primitives::B256, i32, alloy::primitives::B256, u64), + ) -> Result { + let (hash, block_number, parent_hash, timestamp) = tuple; + + // Convert timestamp to `BlockTime` + let secs = + i64::try_from(timestamp).map_err(|_| anyhow!("Timestamp out of range for i64"))?; + let block_time = BlockTime::since_epoch(secs, 0); + + Ok(ExtendedBlockPtr { + hash: hash.into(), + number: block_number, + parent_hash: parent_hash.into(), + timestamp: block_time, + }) + } +} impl From for H256 { fn from(ptr: ExtendedBlockPtr) -> Self { ptr.hash_as_h256() From d177734d794985ba30a20f8e57b3a45769082c6a Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 19:55:20 +0530 Subject: [PATCH 13/44] chain/ethereum: migrate load_block_ptrs_rpc call to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 16 ++++++++-------- graph/src/blockchain/types.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 8d0b3e054dc..7413cbc12f1 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -884,22 +884,22 @@ impl EthereumAdapter { logger: Logger, block_nums: Vec, ) -> impl Stream + Send { - let web3 = self.web3.clone(); + let alloy = self.alloy.clone(); stream::iter_ok::<_, Error>(block_nums.into_iter().map(move |block_num| { - let web3 = web3.clone(); + let alloy = alloy.clone(); retry(format!("load block ptr {}", block_num), &logger) .redact_log_urls(true) .when(|res| !res.is_ok() && !detect_null_block(res)) .no_limit() .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.clone(); + let alloy = alloy.cheap_clone(); async move { - let block = web3 - .eth() - .block(BlockId::Number(Web3BlockNumber::Number(block_num.into()))) - .boxed() + let block = alloy + .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + block_num as u64, + )) .await?; block.ok_or_else(|| { @@ -920,7 +920,7 @@ impl EthereumAdapter { })) .buffered(ENV_VARS.block_batch_size) .filter_map(|b| b) - .map(|b| b.into()) + .map(|b| BlockPtr::from((b.header.hash, b.header.number as i32))) } /// Check if `block_ptr` refers to a block that is on the main chain, according to the Ethereum diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index 7ce9b4dcf18..eb147e8baf7 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -241,6 +241,15 @@ impl From<(H256, i32)> for BlockPtr { } } +impl From<(alloy::primitives::B256, i32)> for BlockPtr { + fn from((hash, number): (alloy::primitives::B256, i32)) -> BlockPtr { + BlockPtr { + hash: hash.into(), + number, + } + } +} + impl From<(Vec, u64)> for BlockPtr { fn from((bytes, number): (Vec, u64)) -> Self { let number = i32::try_from(number).unwrap(); From d806e620d76b1f2ad64573f4fe23adfe6e65b05d Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 20:17:47 +0530 Subject: [PATCH 14/44] graph, chain, runtime: re export alloy from graph crate and use it --- Cargo.lock | 41 ------------------- chain/ethereum/Cargo.toml | 2 - chain/ethereum/src/adapter.rs | 3 +- chain/ethereum/src/ethereum_adapter.rs | 26 +++++++----- chain/ethereum/src/runtime/runtime_adapter.rs | 2 +- graph/src/lib.rs | 1 + runtime/wasm/Cargo.toml | 1 - runtime/wasm/src/to_from/external.rs | 5 ++- 8 files changed, 23 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed88a3b65f7..a5a15372cbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,7 +507,6 @@ dependencies = [ "alloy-rlp", "alloy-serde", "derive_more 2.0.1", - "jsonwebtoken", "rand 0.8.5", "serde", "strum 0.27.1", @@ -3135,8 +3134,6 @@ dependencies = [ name = "graph-chain-ethereum" version = "0.36.0" dependencies = [ - "alloy", - "alloy-rpc-types", "anyhow", "base64 0.22.1", "envconfig", @@ -3285,7 +3282,6 @@ dependencies = [ name = "graph-runtime-wasm" version = "0.36.0" dependencies = [ - "alloy", "anyhow", "async-trait", "bs58 0.4.0", @@ -4329,21 +4325,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "k256" version = "0.13.4" @@ -4949,16 +4930,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -6431,18 +6402,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint 0.4.6", - "num-traits", - "thiserror 2.0.12", - "time", -] - [[package]] name = "siphasher" version = "1.0.1" diff --git a/chain/ethereum/Cargo.toml b/chain/ethereum/Cargo.toml index 5193fa31fb6..04cd034e184 100644 --- a/chain/ethereum/Cargo.toml +++ b/chain/ethereum/Cargo.toml @@ -4,8 +4,6 @@ version.workspace = true edition.workspace = true [dependencies] -alloy.workspace = true -alloy-rpc-types.workspace = true envconfig = "0.11.0" jsonrpc-core = "18.0.0" graph = { path = "../../graph" } diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 477276ba7b9..1602d805eaf 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1,5 +1,3 @@ -use alloy::transports::RpcError; -use alloy::transports::TransportErrorKind; use anyhow::Error; use graph::abi; use graph::blockchain::ChainIdentifier; @@ -9,6 +7,7 @@ use graph::data_source::common::ContractCall; use graph::firehose::CallToFilter; use graph::firehose::CombinedFilter; use graph::firehose::LogFilter; +use graph::prelude::alloy::transports::{RpcError, TransportErrorKind}; use graph::prelude::web3::types::H160; use itertools::Itertools; use prost::Message; diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 7413cbc12f1..94227f40ccd 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1,5 +1,3 @@ -use alloy::primitives::B256; -use alloy::providers::{Provider, ProviderBuilder}; use futures03::{future::BoxFuture, stream::FuturesUnordered}; use graph::abi; use graph::abi::DynSolValueExt; @@ -21,6 +19,7 @@ use graph::futures03::future::try_join_all; use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; +use graph::prelude::alloy; use graph::prelude::tokio::try_join; use graph::slog::o; use graph::tokio::sync::RwLock; @@ -78,7 +77,7 @@ pub struct EthereumAdapter { logger: Logger, provider: String, web3: Arc>, - alloy: Arc, + alloy: Arc, metrics: Arc, supports_eip_1898: bool, call_only: bool, @@ -139,7 +138,12 @@ impl EthereumAdapter { Transport::WS(_web_socket) => todo!(), }; let web3 = Arc::new(Web3::new(transport)); - let alloy = Arc::new(ProviderBuilder::new().connect(&rpc_url).await.unwrap()); + let alloy = Arc::new( + alloy::providers::ProviderBuilder::new() + .connect(&rpc_url) + .await + .unwrap(), + ); EthereumAdapter { logger, @@ -520,11 +524,13 @@ impl EthereumAdapter { } } - fn block_ptr_to_alloy_block_id(&self, block_ptr: &BlockPtr) -> alloy_rpc_types::BlockId { + fn block_ptr_to_alloy_block_id(&self, block_ptr: &BlockPtr) -> alloy::rpc::types::BlockId { if !self.supports_eip_1898 { - alloy_rpc_types::BlockId::number(block_ptr.number as u64) + alloy::rpc::types::BlockId::number(block_ptr.number as u64) } else { - alloy_rpc_types::BlockId::hash(B256::new(*block_ptr.hash_as_h256().as_fixed_bytes())) + alloy::rpc::types::BlockId::hash(alloy::primitives::B256::new( + *block_ptr.hash_as_h256().as_fixed_bytes(), + )) } } @@ -838,7 +844,7 @@ impl EthereumAdapter { async move { let block_result = alloy - .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Number( number as u64, )) .await; @@ -897,7 +903,7 @@ impl EthereumAdapter { let alloy = alloy.cheap_clone(); async move { let block = alloy - .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Number( block_num as u64, )) .await?; @@ -1509,7 +1515,7 @@ impl EthereumAdapterTrait for EthereumAdapter { let alloy = alloy.cheap_clone(); async move { alloy - .get_block_by_number(alloy_rpc_types::BlockNumberOrTag::Number( + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Number( next_number as u64, )) .await diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index ad635e81314..291042cb193 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -23,7 +23,7 @@ use graph::slog::debug; use graph::{ blockchain::{self, BlockPtr, HostFnCtx}, cheap_clone::CheapClone, - prelude::EthereumCallCache, + prelude::{alloy, EthereumCallCache}, runtime::{asc_get, asc_new, AscPtr, HostExportError}, semver::Version, slog::Logger, diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 55a2994f717..2c511c411d5 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -79,6 +79,7 @@ pub use url; /// ``` pub mod prelude { pub use ::anyhow; + pub use alloy; pub use anyhow::{anyhow, Context as _, Error}; pub use async_trait::async_trait; pub use atty; diff --git a/runtime/wasm/Cargo.toml b/runtime/wasm/Cargo.toml index 5c2bd2fe06b..2ca24759d0d 100644 --- a/runtime/wasm/Cargo.toml +++ b/runtime/wasm/Cargo.toml @@ -4,7 +4,6 @@ version.workspace = true edition.workspace = true [dependencies] -alloy = { workspace = true } async-trait = "0.1.50" hex = "0.4.3" graph = { path = "../../graph" } diff --git a/runtime/wasm/src/to_from/external.rs b/runtime/wasm/src/to_from/external.rs index fcfde250853..6602a17f2b1 100644 --- a/runtime/wasm/src/to_from/external.rs +++ b/runtime/wasm/src/to_from/external.rs @@ -8,8 +8,11 @@ use graph::runtime::{ asc_get, asc_new, AscIndexId, AscPtr, AscType, AscValue, HostExportError, ToAscObj, }; use graph::{data::store, runtime::DeterministicHostError}; -use graph::{prelude::serde_json, runtime::FromAscObj}; use graph::{prelude::web3::types as web3, runtime::AscHeap}; +use graph::{ + prelude::{alloy, serde_json}, + runtime::FromAscObj, +}; use graph_runtime_derive::AscType; use crate::asc_abi::class::*; From 40009f8e3b85307516eab7f3469815bd77a0623d Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 20:34:06 +0530 Subject: [PATCH 15/44] chain/ethereum: migrate genesis block fetching call to use alloy in net_identifiers --- chain/ethereum/src/ethereum_adapter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 94227f40ccd..0b5dd61ea35 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1235,7 +1235,7 @@ impl EthereumAdapterTrait for EthereumAdapter { }) .boxed(); - let web3 = self.web3.clone(); + let alloy_provider = self.alloy.clone(); let metrics = self.metrics.clone(); let provider = self.provider().to_string(); let retry_log_message = format!( @@ -1247,20 +1247,20 @@ impl EthereumAdapterTrait for EthereumAdapter { .no_limit() .timeout_secs(30) .run(move || { - let web3 = web3.cheap_clone(); + let alloy_genesis = alloy_provider.cheap_clone(); let metrics = metrics.cheap_clone(); let provider = provider.clone(); async move { - web3.eth() - .block(BlockId::Number(Web3BlockNumber::Number( - ENV_VARS.genesis_block_number.into(), - ))) + alloy_genesis + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Number( + ENV_VARS.genesis_block_number as u64, + )) .await .map_err(|e| { metrics.set_status(ProviderStatus::GenesisFail, &provider); e })? - .and_then(|gen_block| gen_block.hash.map(BlockHash::from)) + .map(|gen_block| BlockHash::from(gen_block.header.hash)) .ok_or_else(|| anyhow!("Ethereum node could not find genesis block")) } }) From 617a8470f881f8c4a81b1f819438e27d9bb0afe6 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 20:49:49 +0530 Subject: [PATCH 16/44] chain/ethereum: migrate latest_block_header call to use alloy --- chain/ethereum/src/adapter.rs | 7 +++---- chain/ethereum/src/ethereum_adapter.rs | 23 ++++++++++++----------- chain/ethereum/src/ingestor.rs | 5 +---- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 1602d805eaf..3a6a9e53906 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -26,6 +26,8 @@ use graph::{ petgraph::{self, graphmap::GraphMap}, }; +use graph::blockchain::BlockPtr; + const COMBINED_FILTER_TYPE_URL: &str = "type.googleapis.com/sf.ethereum.transform.v1.CombinedFilter"; @@ -1083,10 +1085,7 @@ pub trait EthereumAdapter: Send + Sync + 'static { async fn latest_block(&self, logger: &Logger) -> Result; /// Get the latest block, with only the header and transaction hashes. - async fn latest_block_header( - &self, - logger: &Logger, - ) -> Result, bc::IngestorError>; + async fn latest_block_header(&self, logger: &Logger) -> Result; async fn load_block( &self, diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 0b5dd61ea35..030580d4b0a 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1288,26 +1288,27 @@ impl EthereumAdapterTrait for EthereumAdapter { Ok(ident) } - async fn latest_block_header( - &self, - logger: &Logger, - ) -> Result, IngestorError> { - let web3 = self.web3.clone(); + async fn latest_block_header(&self, logger: &Logger) -> Result { + let alloy = self.alloy.clone(); retry("eth_getBlockByNumber(latest) no txs RPC call", logger) .redact_log_urls(true) .no_limit() .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - let block_opt = web3 - .eth() - .block(Web3BlockNumber::Latest.into()) + let block_opt = alloy + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Latest) .await .map_err(|e| anyhow!("could not get latest block from Ethereum: {}", e))?; - block_opt - .ok_or_else(|| anyhow!("no latest block returned from Ethereum").into()) + let block = block_opt + .ok_or_else(|| anyhow!("no latest block returned from Ethereum"))?; + + Ok(BlockPtr::from(( + block.header.hash, + block.header.number as i32, + ))) } }) .map_err(move |e| { diff --git a/chain/ethereum/src/ingestor.rs b/chain/ethereum/src/ingestor.rs index a29aa8d17bd..aa5dc4d83de 100644 --- a/chain/ethereum/src/ingestor.rs +++ b/chain/ethereum/src/ingestor.rs @@ -206,10 +206,7 @@ impl PollingBlockIngestor { logger: &Logger, eth_adapter: &Arc, ) -> Result { - eth_adapter - .latest_block_header(&logger) - .await - .map(|block| block.into()) + eth_adapter.latest_block_header(&logger).await } async fn eth_adapter(&self) -> anyhow::Result> { From ad48ab717cadfb1f7d3f92bfaa46b4dc1df0e9a7 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 20:51:31 +0530 Subject: [PATCH 17/44] chain/ethereum: rename latest_block_header to latest_block_ptr --- chain/ethereum/src/adapter.rs | 2 +- chain/ethereum/src/ethereum_adapter.rs | 2 +- chain/ethereum/src/ingestor.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 3a6a9e53906..6189adc3e3b 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1085,7 +1085,7 @@ pub trait EthereumAdapter: Send + Sync + 'static { async fn latest_block(&self, logger: &Logger) -> Result; /// Get the latest block, with only the header and transaction hashes. - async fn latest_block_header(&self, logger: &Logger) -> Result; + async fn latest_block_ptr(&self, logger: &Logger) -> Result; async fn load_block( &self, diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 030580d4b0a..6708d0afbd9 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -1288,7 +1288,7 @@ impl EthereumAdapterTrait for EthereumAdapter { Ok(ident) } - async fn latest_block_header(&self, logger: &Logger) -> Result { + async fn latest_block_ptr(&self, logger: &Logger) -> Result { let alloy = self.alloy.clone(); retry("eth_getBlockByNumber(latest) no txs RPC call", logger) .redact_log_urls(true) diff --git a/chain/ethereum/src/ingestor.rs b/chain/ethereum/src/ingestor.rs index aa5dc4d83de..92293510fae 100644 --- a/chain/ethereum/src/ingestor.rs +++ b/chain/ethereum/src/ingestor.rs @@ -206,7 +206,7 @@ impl PollingBlockIngestor { logger: &Logger, eth_adapter: &Arc, ) -> Result { - eth_adapter.latest_block_header(&logger).await + eth_adapter.latest_block_ptr(&logger).await } async fn eth_adapter(&self) -> anyhow::Result> { From ee073eaadba1d28aa3ac4bfd415d867d2847fc13 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 18 Jun 2025 20:55:10 +0530 Subject: [PATCH 18/44] chain/ethereum: remove unused latest_block adapter method --- chain/ethereum/src/adapter.rs | 3 --- chain/ethereum/src/ethereum_adapter.rs | 30 ++------------------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 6189adc3e3b..2d2a00e0448 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1081,9 +1081,6 @@ pub trait EthereumAdapter: Send + Sync + 'static { /// connected to. async fn net_identifiers(&self) -> Result; - /// Get the latest block, including full transactions. - async fn latest_block(&self, logger: &Logger) -> Result; - /// Get the latest block, with only the header and transaction hashes. async fn latest_block_ptr(&self, logger: &Logger) -> Result; diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 6708d0afbd9..e98ff0f1d7b 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -32,8 +32,8 @@ use graph::{ web3::{ self, types::{ - BlockId, BlockNumber as Web3BlockNumber, Bytes, CallRequest, Filter, FilterBuilder, - Log, Transaction, TransactionReceipt, H256, + BlockId, Bytes, CallRequest, Filter, FilterBuilder, Log, Transaction, + TransactionReceipt, H256, }, }, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, @@ -1319,32 +1319,6 @@ impl EthereumAdapterTrait for EthereumAdapter { .await } - async fn latest_block(&self, logger: &Logger) -> Result { - let web3 = self.web3.clone(); - retry("eth_getBlockByNumber(latest) with txs RPC call", logger) - .redact_log_urls(true) - .no_limit() - .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || { - let web3 = web3.cheap_clone(); - async move { - let block_opt = web3 - .eth() - .block_with_txs(Web3BlockNumber::Latest.into()) - .await - .map_err(|e| anyhow!("could not get latest block from Ethereum: {}", e))?; - block_opt - .ok_or_else(|| anyhow!("no latest block returned from Ethereum").into()) - } - }) - .map_err(move |e| { - e.into_inner().unwrap_or_else(move || { - anyhow!("Ethereum node took too long to return latest block").into() - }) - }) - .await - } - async fn load_block( &self, logger: &Logger, From 255d2270ca27c69e0e18bce76deaeec4463b5e25 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 19 Jun 2025 12:03:29 +0530 Subject: [PATCH 19/44] chain/ethereum: Refactor eth_call method in ethereum adapter --- chain/ethereum/src/ethereum_adapter.rs | 245 +++++++++++++------------ 1 file changed, 130 insertions(+), 115 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index e98ff0f1d7b..e7acc822d75 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -115,6 +115,134 @@ impl CheapClone for EthereumAdapter { } impl EthereumAdapter { + // ------------------------------------------------------------------ + // Constants and helper utilities used across eth_call handling + // ------------------------------------------------------------------ + + // Try to check if the call was reverted. The JSON-RPC response for reverts is + // not standardized, so we have ad-hoc checks for each Ethereum client. + + // 0xfe is the "designated bad instruction" of the EVM, and Solidity uses it for + // asserts. + const PARITY_BAD_INSTRUCTION_FE: &str = "Bad instruction fe"; + + // 0xfd is REVERT, but on some contracts, and only on older blocks, + // this happens. Makes sense to consider it a revert as well. + const PARITY_BAD_INSTRUCTION_FD: &str = "Bad instruction fd"; + + const PARITY_BAD_JUMP_PREFIX: &str = "Bad jump"; + const PARITY_STACK_LIMIT_PREFIX: &str = "Out of stack"; + + // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61. + const PARITY_OUT_OF_GAS: &str = "Out of gas"; + + // Also covers Nethermind reverts + const PARITY_VM_EXECUTION_ERROR: i64 = -32015; + const PARITY_REVERT_PREFIX: &str = "revert"; + + const XDAI_REVERT: &str = "revert"; + + // Deterministic Geth execution errors. We might need to expand this as + // subgraphs come across other errors. See + // https://github.com/ethereum/go-ethereum/blob/cd57d5cd38ef692de8fbedaa56598b4e9fbfbabc/core/vm/errors.go + const GETH_EXECUTION_ERRORS: &[&str] = &[ + // The "revert" substring covers a few known error messages, including: + // Hardhat: "error: transaction reverted", + // Ganache and Moonbeam: "vm exception while processing transaction: revert", + // Geth: "execution reverted" + // And others. + "revert", + "invalid jump destination", + "invalid opcode", + // Ethereum says 1024 is the stack sizes limit, so this is deterministic. + "stack limit reached 1024", + // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61 for why the gas limit is considered deterministic. + "out of gas", + "stack underflow", + ]; + + /// Helper that checks if a geth style RPC error message corresponds to a revert. + fn is_geth_revert_message(message: &str) -> bool { + let env_geth_call_errors = ENV_VARS.geth_eth_call_errors.iter(); + let mut execution_errors = Self::GETH_EXECUTION_ERRORS + .iter() + .copied() + .chain(env_geth_call_errors.map(|s| s.as_str())); + execution_errors.any(|e| message.to_lowercase().contains(e)) + } + + /// Decode a Solidity revert(reason) payload, returning the reason string when possible. + fn as_solidity_revert_reason(bytes: &[u8]) -> Option { + let selector = &tiny_keccak::keccak256(b"Error(string)")[..4]; + if bytes.len() >= 4 && &bytes[..4] == selector { + abi::DynSolType::String + .abi_decode(&bytes[4..]) + .ok() + .and_then(|val| val.clone().as_str().map(ToOwned::to_owned)) + } else { + None + } + } + + /// Interpret the error returned by `eth_call`, distinguishing genuine failures from + /// EVM reverts. Returns `Ok(Null)` for reverts or a proper error otherwise. + fn interpret_eth_call_error( + logger: &Logger, + err: web3::Error, + ) -> Result { + fn reverted(logger: &Logger, reason: &str) -> Result { + info!(logger, "Contract call reverted"; "reason" => reason); + Ok(call::Retval::Null) + } + + if let web3::Error::Rpc(rpc_error) = &err { + if Self::is_geth_revert_message(&rpc_error.message) { + return reverted(logger, &rpc_error.message); + } + } + + if let web3::Error::Rpc(rpc_error) = &err { + let code = rpc_error.code.code(); + let data = rpc_error.data.as_ref().and_then(|d| d.as_str()); + + if code == Self::PARITY_VM_EXECUTION_ERROR { + if let Some(data) = data { + if Self::is_parity_revert(data) { + return reverted(logger, &Self::parity_revert_reason(data)); + } + } + } + } + + Err(ContractCallError::Web3Error(err)) + } + + fn is_parity_revert(data: &str) -> bool { + data.to_lowercase().starts_with(Self::PARITY_REVERT_PREFIX) + || data.starts_with(Self::PARITY_BAD_JUMP_PREFIX) + || data.starts_with(Self::PARITY_STACK_LIMIT_PREFIX) + || data == Self::PARITY_BAD_INSTRUCTION_FE + || data == Self::PARITY_BAD_INSTRUCTION_FD + || data == Self::PARITY_OUT_OF_GAS + || data == Self::XDAI_REVERT + } + + /// Checks if the given `web3::Error` corresponds to a Parity / Nethermind style EVM + /// revert and, if so, tries to extract a human-readable revert reason. Returns `Some` + /// with the reason when the error is identified as a revert, otherwise `None`. + fn parity_revert_reason(data: &str) -> String { + if data == Self::PARITY_BAD_INSTRUCTION_FE { + return Self::PARITY_BAD_INSTRUCTION_FE.to_owned(); + } + + // Otherwise try to decode a Solidity revert reason payload. + let payload = data.trim_start_matches(Self::PARITY_REVERT_PREFIX); + hex::decode(payload) + .ok() + .and_then(|decoded| Self::as_solidity_revert_reason(&decoded)) + .unwrap_or_else(|| "no reason".to_owned()) + } + pub fn is_call_only(&self) -> bool { self.call_only } @@ -609,11 +737,6 @@ impl EthereumAdapter { block_ptr: BlockPtr, gas: Option, ) -> Result { - fn reverted(logger: &Logger, reason: &str) -> Result { - info!(logger, "Contract call reverted"; "reason" => reason); - Ok(call::Retval::Null) - } - let web3 = self.web3.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); @@ -642,122 +765,14 @@ impl EthereumAdapter { }; let result = web3.eth().call(req, Some(block_id)).boxed().await; - // Try to check if the call was reverted. The JSON-RPC response for reverts is - // not standardized, so we have ad-hoc checks for each Ethereum client. - - // 0xfe is the "designated bad instruction" of the EVM, and Solidity uses it for - // asserts. - const PARITY_BAD_INSTRUCTION_FE: &str = "Bad instruction fe"; - - // 0xfd is REVERT, but on some contracts, and only on older blocks, - // this happens. Makes sense to consider it a revert as well. - const PARITY_BAD_INSTRUCTION_FD: &str = "Bad instruction fd"; - - const PARITY_BAD_JUMP_PREFIX: &str = "Bad jump"; - const PARITY_STACK_LIMIT_PREFIX: &str = "Out of stack"; - - // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61. - const PARITY_OUT_OF_GAS: &str = "Out of gas"; - - // Also covers Nethermind reverts - const PARITY_VM_EXECUTION_ERROR: i64 = -32015; - const PARITY_REVERT_PREFIX: &str = "revert"; - - const XDAI_REVERT: &str = "revert"; - - // Deterministic Geth execution errors. We might need to expand this as - // subgraphs come across other errors. See - // https://github.com/ethereum/go-ethereum/blob/cd57d5cd38ef692de8fbedaa56598b4e9fbfbabc/core/vm/errors.go - const GETH_EXECUTION_ERRORS: &[&str] = &[ - // The "revert" substring covers a few known error messages, including: - // Hardhat: "error: transaction reverted", - // Ganache and Moonbeam: "vm exception while processing transaction: revert", - // Geth: "execution reverted" - // And others. - "revert", - "invalid jump destination", - "invalid opcode", - // Ethereum says 1024 is the stack sizes limit, so this is deterministic. - "stack limit reached 1024", - // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61 for why the gas limit is considered deterministic. - "out of gas", - "stack underflow", - ]; - - let env_geth_call_errors = ENV_VARS.geth_eth_call_errors.iter(); - let mut geth_execution_errors = GETH_EXECUTION_ERRORS - .iter() - .copied() - .chain(env_geth_call_errors.map(|s| s.as_str())); - - let as_solidity_revert_with_reason = |bytes: &[u8]| { - let solidity_revert_function_selector = - &tiny_keccak::keccak256(b"Error(string)")[..4]; - - match bytes.len() >= 4 && &bytes[..4] == solidity_revert_function_selector { - false => None, - true => abi::DynSolType::String - .abi_decode(&bytes[4..]) - .ok() - .and_then(|val| val.clone().as_str().map(ToOwned::to_owned)), - } - }; - match result { - // A successful response. Ok(bytes) => Ok(call::Retval::Value(scalar::Bytes::from(bytes))), - - // Check for Geth revert. - Err(web3::Error::Rpc(rpc_error)) - if geth_execution_errors - .any(|e| rpc_error.message.to_lowercase().contains(e)) => - { - reverted(&logger, &rpc_error.message) - } - - // Check for Parity revert. - Err(web3::Error::Rpc(ref rpc_error)) - if rpc_error.code.code() == PARITY_VM_EXECUTION_ERROR => - { - match rpc_error.data.as_ref().and_then(|d| d.as_str()) { - Some(data) - if data.to_lowercase().starts_with(PARITY_REVERT_PREFIX) - || data.starts_with(PARITY_BAD_JUMP_PREFIX) - || data.starts_with(PARITY_STACK_LIMIT_PREFIX) - || data == PARITY_BAD_INSTRUCTION_FE - || data == PARITY_BAD_INSTRUCTION_FD - || data == PARITY_OUT_OF_GAS - || data == XDAI_REVERT => - { - let reason = if data == PARITY_BAD_INSTRUCTION_FE { - PARITY_BAD_INSTRUCTION_FE.to_owned() - } else { - let payload = data.trim_start_matches(PARITY_REVERT_PREFIX); - hex::decode(payload) - .ok() - .and_then(|payload| { - as_solidity_revert_with_reason(&payload) - }) - .unwrap_or("no reason".to_owned()) - }; - reverted(&logger, &reason) - } - - // The VM execution error was not identified as a revert. - _ => Err(ContractCallError::Web3Error(web3::Error::Rpc( - rpc_error.clone(), - ))), - } - } - - // The error was not identified as a revert. - Err(err) => Err(ContractCallError::Web3Error(err)), + Err(err) => Self::interpret_eth_call_error(&logger, err), } } }) - .map_err(|e| e.into_inner().unwrap_or(ContractCallError::Timeout)) - .boxed() .await + .map_err(|e| e.into_inner().unwrap_or(ContractCallError::Timeout)) } async fn call_and_cache( From 28c39c256bf2b81e29dd0a5cea861b3c3d23bb12 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 19 Jun 2025 13:20:18 +0530 Subject: [PATCH 20/44] chain/ethereum: Move eth_call helper functions to separate module --- chain/ethereum/src/call_helper.rs | 135 +++++++++++++++++++++++++ chain/ethereum/src/ethereum_adapter.rs | 133 +----------------------- chain/ethereum/src/lib.rs | 1 + 3 files changed, 139 insertions(+), 130 deletions(-) create mode 100644 chain/ethereum/src/call_helper.rs diff --git a/chain/ethereum/src/call_helper.rs b/chain/ethereum/src/call_helper.rs new file mode 100644 index 00000000000..79a2e7dc78a --- /dev/null +++ b/chain/ethereum/src/call_helper.rs @@ -0,0 +1,135 @@ +use crate::{ContractCallError, ENV_VARS}; +use graph::{ + abi, + data::store::ethereum::call, + prelude::{web3, Logger}, + slog::info, +}; + +// ------------------------------------------------------------------ +// Constants and helper utilities used across eth_call handling +// ------------------------------------------------------------------ + +// Try to check if the call was reverted. The JSON-RPC response for reverts is +// not standardized, so we have ad-hoc checks for each Ethereum client. + +// 0xfe is the "designated bad instruction" of the EVM, and Solidity uses it for +// asserts. +const PARITY_BAD_INSTRUCTION_FE: &str = "Bad instruction fe"; + +// 0xfd is REVERT, but on some contracts, and only on older blocks, +// this happens. Makes sense to consider it a revert as well. +const PARITY_BAD_INSTRUCTION_FD: &str = "Bad instruction fd"; + +const PARITY_BAD_JUMP_PREFIX: &str = "Bad jump"; +const PARITY_STACK_LIMIT_PREFIX: &str = "Out of stack"; + +// See f0af4ab0-6b7c-4b68-9141-5b79346a5f61. +const PARITY_OUT_OF_GAS: &str = "Out of gas"; + +// Also covers Nethermind reverts +const PARITY_VM_EXECUTION_ERROR: i64 = -32015; +const PARITY_REVERT_PREFIX: &str = "revert"; + +const XDAI_REVERT: &str = "revert"; + +// Deterministic Geth execution errors. We might need to expand this as +// subgraphs come across other errors. See +// https://github.com/ethereum/go-ethereum/blob/cd57d5cd38ef692de8fbedaa56598b4e9fbfbabc/core/vm/errors.go +const GETH_EXECUTION_ERRORS: &[&str] = &[ + // The "revert" substring covers a few known error messages, including: + // Hardhat: "error: transaction reverted", + // Ganache and Moonbeam: "vm exception while processing transaction: revert", + // Geth: "execution reverted" + // And others. + "revert", + "invalid jump destination", + "invalid opcode", + // Ethereum says 1024 is the stack sizes limit, so this is deterministic. + "stack limit reached 1024", + // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61 for why the gas limit is considered deterministic. + "out of gas", + "stack underflow", +]; + +/// Helper that checks if a geth style RPC error message corresponds to a revert. +fn is_geth_revert_message(message: &str) -> bool { + let env_geth_call_errors = ENV_VARS.geth_eth_call_errors.iter(); + let mut execution_errors = GETH_EXECUTION_ERRORS + .iter() + .copied() + .chain(env_geth_call_errors.map(|s| s.as_str())); + execution_errors.any(|e| message.to_lowercase().contains(e)) +} + +/// Decode a Solidity revert(reason) payload, returning the reason string when possible. +fn as_solidity_revert_reason(bytes: &[u8]) -> Option { + let selector = &tiny_keccak::keccak256(b"Error(string)")[..4]; + if bytes.len() >= 4 && &bytes[..4] == selector { + abi::DynSolType::String + .abi_decode(&bytes[4..]) + .ok() + .and_then(|val| val.clone().as_str().map(ToOwned::to_owned)) + } else { + None + } +} + +/// Interpret the error returned by `eth_call`, distinguishing genuine failures from +/// EVM reverts. Returns `Ok(Null)` for reverts or a proper error otherwise. +pub fn interpret_eth_call_error( + logger: &Logger, + err: web3::Error, +) -> Result { + fn reverted(logger: &Logger, reason: &str) -> Result { + info!(logger, "Contract call reverted"; "reason" => reason); + Ok(call::Retval::Null) + } + + if let web3::Error::Rpc(rpc_error) = &err { + if is_geth_revert_message(&rpc_error.message) { + return reverted(logger, &rpc_error.message); + } + } + + if let web3::Error::Rpc(rpc_error) = &err { + let code = rpc_error.code.code(); + let data = rpc_error.data.as_ref().and_then(|d| d.as_str()); + + if code == PARITY_VM_EXECUTION_ERROR { + if let Some(data) = data { + if is_parity_revert(data) { + return reverted(logger, &parity_revert_reason(data)); + } + } + } + } + + Err(ContractCallError::Web3Error(err)) +} + +fn is_parity_revert(data: &str) -> bool { + data.to_lowercase().starts_with(PARITY_REVERT_PREFIX) + || data.starts_with(PARITY_BAD_JUMP_PREFIX) + || data.starts_with(PARITY_STACK_LIMIT_PREFIX) + || data == PARITY_BAD_INSTRUCTION_FE + || data == PARITY_BAD_INSTRUCTION_FD + || data == PARITY_OUT_OF_GAS + || data == XDAI_REVERT +} + +/// Checks if the given `web3::Error` corresponds to a Parity / Nethermind style EVM +/// revert and, if so, tries to extract a human-readable revert reason. Returns `Some` +/// with the reason when the error is identified as a revert, otherwise `None`. +fn parity_revert_reason(data: &str) -> String { + if data == PARITY_BAD_INSTRUCTION_FE { + return PARITY_BAD_INSTRUCTION_FE.to_owned(); + } + + // Otherwise try to decode a Solidity revert reason payload. + let payload = data.trim_start_matches(PARITY_REVERT_PREFIX); + hex::decode(payload) + .ok() + .and_then(|decoded| as_solidity_revert_reason(&decoded)) + .unwrap_or_else(|| "no reason".to_owned()) +} diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index e7acc822d75..d5512b9f637 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -28,7 +28,7 @@ use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ anyhow::{self, anyhow, bail, ensure, Context}, - async_trait, debug, error, hex, info, retry, serde_json as json, tiny_keccak, trace, warn, + async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, web3::{ self, types::{ @@ -56,6 +56,7 @@ use std::time::Instant; use crate::adapter::EthereumRpcError; use crate::adapter::ProviderStatus; +use crate::call_helper::interpret_eth_call_error; use crate::chain::BlockFinality; use crate::trigger::LogRef; use crate::Chain; @@ -115,134 +116,6 @@ impl CheapClone for EthereumAdapter { } impl EthereumAdapter { - // ------------------------------------------------------------------ - // Constants and helper utilities used across eth_call handling - // ------------------------------------------------------------------ - - // Try to check if the call was reverted. The JSON-RPC response for reverts is - // not standardized, so we have ad-hoc checks for each Ethereum client. - - // 0xfe is the "designated bad instruction" of the EVM, and Solidity uses it for - // asserts. - const PARITY_BAD_INSTRUCTION_FE: &str = "Bad instruction fe"; - - // 0xfd is REVERT, but on some contracts, and only on older blocks, - // this happens. Makes sense to consider it a revert as well. - const PARITY_BAD_INSTRUCTION_FD: &str = "Bad instruction fd"; - - const PARITY_BAD_JUMP_PREFIX: &str = "Bad jump"; - const PARITY_STACK_LIMIT_PREFIX: &str = "Out of stack"; - - // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61. - const PARITY_OUT_OF_GAS: &str = "Out of gas"; - - // Also covers Nethermind reverts - const PARITY_VM_EXECUTION_ERROR: i64 = -32015; - const PARITY_REVERT_PREFIX: &str = "revert"; - - const XDAI_REVERT: &str = "revert"; - - // Deterministic Geth execution errors. We might need to expand this as - // subgraphs come across other errors. See - // https://github.com/ethereum/go-ethereum/blob/cd57d5cd38ef692de8fbedaa56598b4e9fbfbabc/core/vm/errors.go - const GETH_EXECUTION_ERRORS: &[&str] = &[ - // The "revert" substring covers a few known error messages, including: - // Hardhat: "error: transaction reverted", - // Ganache and Moonbeam: "vm exception while processing transaction: revert", - // Geth: "execution reverted" - // And others. - "revert", - "invalid jump destination", - "invalid opcode", - // Ethereum says 1024 is the stack sizes limit, so this is deterministic. - "stack limit reached 1024", - // See f0af4ab0-6b7c-4b68-9141-5b79346a5f61 for why the gas limit is considered deterministic. - "out of gas", - "stack underflow", - ]; - - /// Helper that checks if a geth style RPC error message corresponds to a revert. - fn is_geth_revert_message(message: &str) -> bool { - let env_geth_call_errors = ENV_VARS.geth_eth_call_errors.iter(); - let mut execution_errors = Self::GETH_EXECUTION_ERRORS - .iter() - .copied() - .chain(env_geth_call_errors.map(|s| s.as_str())); - execution_errors.any(|e| message.to_lowercase().contains(e)) - } - - /// Decode a Solidity revert(reason) payload, returning the reason string when possible. - fn as_solidity_revert_reason(bytes: &[u8]) -> Option { - let selector = &tiny_keccak::keccak256(b"Error(string)")[..4]; - if bytes.len() >= 4 && &bytes[..4] == selector { - abi::DynSolType::String - .abi_decode(&bytes[4..]) - .ok() - .and_then(|val| val.clone().as_str().map(ToOwned::to_owned)) - } else { - None - } - } - - /// Interpret the error returned by `eth_call`, distinguishing genuine failures from - /// EVM reverts. Returns `Ok(Null)` for reverts or a proper error otherwise. - fn interpret_eth_call_error( - logger: &Logger, - err: web3::Error, - ) -> Result { - fn reverted(logger: &Logger, reason: &str) -> Result { - info!(logger, "Contract call reverted"; "reason" => reason); - Ok(call::Retval::Null) - } - - if let web3::Error::Rpc(rpc_error) = &err { - if Self::is_geth_revert_message(&rpc_error.message) { - return reverted(logger, &rpc_error.message); - } - } - - if let web3::Error::Rpc(rpc_error) = &err { - let code = rpc_error.code.code(); - let data = rpc_error.data.as_ref().and_then(|d| d.as_str()); - - if code == Self::PARITY_VM_EXECUTION_ERROR { - if let Some(data) = data { - if Self::is_parity_revert(data) { - return reverted(logger, &Self::parity_revert_reason(data)); - } - } - } - } - - Err(ContractCallError::Web3Error(err)) - } - - fn is_parity_revert(data: &str) -> bool { - data.to_lowercase().starts_with(Self::PARITY_REVERT_PREFIX) - || data.starts_with(Self::PARITY_BAD_JUMP_PREFIX) - || data.starts_with(Self::PARITY_STACK_LIMIT_PREFIX) - || data == Self::PARITY_BAD_INSTRUCTION_FE - || data == Self::PARITY_BAD_INSTRUCTION_FD - || data == Self::PARITY_OUT_OF_GAS - || data == Self::XDAI_REVERT - } - - /// Checks if the given `web3::Error` corresponds to a Parity / Nethermind style EVM - /// revert and, if so, tries to extract a human-readable revert reason. Returns `Some` - /// with the reason when the error is identified as a revert, otherwise `None`. - fn parity_revert_reason(data: &str) -> String { - if data == Self::PARITY_BAD_INSTRUCTION_FE { - return Self::PARITY_BAD_INSTRUCTION_FE.to_owned(); - } - - // Otherwise try to decode a Solidity revert reason payload. - let payload = data.trim_start_matches(Self::PARITY_REVERT_PREFIX); - hex::decode(payload) - .ok() - .and_then(|decoded| Self::as_solidity_revert_reason(&decoded)) - .unwrap_or_else(|| "no reason".to_owned()) - } - pub fn is_call_only(&self) -> bool { self.call_only } @@ -767,7 +640,7 @@ impl EthereumAdapter { match result { Ok(bytes) => Ok(call::Retval::Value(scalar::Bytes::from(bytes))), - Err(err) => Self::interpret_eth_call_error(&logger, err), + Err(err) => interpret_eth_call_error(&logger, err), } } }) diff --git a/chain/ethereum/src/lib.rs b/chain/ethereum/src/lib.rs index fa76f70d799..8850764d63b 100644 --- a/chain/ethereum/src/lib.rs +++ b/chain/ethereum/src/lib.rs @@ -1,5 +1,6 @@ mod adapter; mod buffered_call_cache; +mod call_helper; mod capabilities; pub mod codec; mod data_source; From 2e9746762d2e0dc0f9971c0afa46665e4c0028c4 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 19 Jun 2025 16:31:13 +0530 Subject: [PATCH 21/44] chain/ethereum: Migrate eth_call to use alloy --- chain/ethereum/src/adapter.rs | 2 + chain/ethereum/src/call_helper.rs | 21 +++++----- chain/ethereum/src/ethereum_adapter.rs | 55 ++++++++++---------------- graph/src/data/store/scalar/bytes.rs | 6 +++ 4 files changed, 41 insertions(+), 43 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 2d2a00e0448..ee61da770a9 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -112,6 +112,8 @@ pub enum ContractCallError { EncodingError(anyhow::Error), #[error("call error: {0}")] Web3Error(web3::Error), + #[error("call error: {0}")] + AlloyError(RpcError), #[error("ethereum node took too long to perform call")] Timeout, #[error("internal error: {0}")] diff --git a/chain/ethereum/src/call_helper.rs b/chain/ethereum/src/call_helper.rs index 79a2e7dc78a..58eab4ba4d6 100644 --- a/chain/ethereum/src/call_helper.rs +++ b/chain/ethereum/src/call_helper.rs @@ -2,7 +2,10 @@ use crate::{ContractCallError, ENV_VARS}; use graph::{ abi, data::store::ethereum::call, - prelude::{web3, Logger}, + prelude::{ + alloy::transports::{RpcError, TransportErrorKind}, + Logger, + }, slog::info, }; @@ -79,33 +82,33 @@ fn as_solidity_revert_reason(bytes: &[u8]) -> Option { /// EVM reverts. Returns `Ok(Null)` for reverts or a proper error otherwise. pub fn interpret_eth_call_error( logger: &Logger, - err: web3::Error, + err: RpcError, ) -> Result { fn reverted(logger: &Logger, reason: &str) -> Result { info!(logger, "Contract call reverted"; "reason" => reason); Ok(call::Retval::Null) } - if let web3::Error::Rpc(rpc_error) = &err { + if let RpcError::ErrorResp(rpc_error) = &err { if is_geth_revert_message(&rpc_error.message) { return reverted(logger, &rpc_error.message); } } - if let web3::Error::Rpc(rpc_error) = &err { - let code = rpc_error.code.code(); - let data = rpc_error.data.as_ref().and_then(|d| d.as_str()); + if let RpcError::ErrorResp(rpc_error) = &err { + let code = rpc_error.code; + let data = rpc_error.data.as_ref().map(|d| d.to_string()); if code == PARITY_VM_EXECUTION_ERROR { if let Some(data) = data { - if is_parity_revert(data) { - return reverted(logger, &parity_revert_reason(data)); + if is_parity_revert(&data) { + return reverted(logger, &parity_revert_reason(&data)); } } } } - Err(ContractCallError::Web3Error(err)) + Err(ContractCallError::AlloyError(err)) } fn is_parity_revert(data: &str) -> bool { diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index d5512b9f637..e1e522a6da0 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -20,6 +20,7 @@ use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; use graph::prelude::alloy; +use graph::prelude::alloy::rpc::types::{TransactionInput, TransactionRequest}; use graph::prelude::tokio::try_join; use graph::slog::o; use graph::tokio::sync::RwLock; @@ -31,10 +32,7 @@ use graph::{ async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, web3::{ self, - types::{ - BlockId, Bytes, CallRequest, Filter, FilterBuilder, Log, Transaction, - TransactionReceipt, H256, - }, + types::{BlockId, Filter, FilterBuilder, Log, Transaction, TransactionReceipt, H256}, }, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, TimeoutError, @@ -514,18 +512,7 @@ impl EthereumAdapter { .boxed() } - // Method to determine block_id based on support for EIP-1898 - fn block_ptr_to_id(&self, block_ptr: &BlockPtr) -> BlockId { - // Ganache does not support calls by block hash. - // See https://github.com/trufflesuite/ganache-cli/issues/973 - if !self.supports_eip_1898 { - BlockId::Number(block_ptr.number.into()) - } else { - BlockId::Hash(block_ptr.hash_as_h256()) - } - } - - fn block_ptr_to_alloy_block_id(&self, block_ptr: &BlockPtr) -> alloy::rpc::types::BlockId { + fn block_ptr_to_id(&self, block_ptr: &BlockPtr) -> alloy::rpc::types::BlockId { if !self.supports_eip_1898 { alloy::rpc::types::BlockId::number(block_ptr.number as u64) } else { @@ -544,7 +531,7 @@ impl EthereumAdapter { let alloy = self.alloy.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); - let block_id = self.block_ptr_to_alloy_block_id(&block_ptr); + let block_id = self.block_ptr_to_id(&block_ptr); let retry_log_message = format!("eth_getCode RPC call for block {}", block_ptr); retry(retry_log_message, &logger) @@ -578,7 +565,7 @@ impl EthereumAdapter { let alloy = self.alloy.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); - let block_id = self.block_ptr_to_alloy_block_id(&block_ptr); + let block_id = self.block_ptr_to_id(&block_ptr); let retry_log_message = format!("eth_getBalance RPC call for block {}", block_ptr); retry(retry_log_message, &logger) @@ -610,10 +597,10 @@ impl EthereumAdapter { block_ptr: BlockPtr, gas: Option, ) -> Result { - let web3 = self.web3.clone(); + let alloy = self.alloy.clone(); let logger = Logger::new(&logger, o!("provider" => self.provider.clone())); - let block_id = self.block_ptr_to_id(&block_ptr); + let alloy_block_id = self.block_ptr_to_id(&block_ptr); let retry_log_message = format!("eth_call RPC call for block {}", block_ptr); retry(retry_log_message, &logger) .redact_log_urls(true) @@ -621,22 +608,22 @@ impl EthereumAdapter { .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { let call_data = call_data.clone(); - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); let logger = logger.cheap_clone(); async move { - let req = CallRequest { - to: Some(call_data.address), - gas: gas.map(|val| web3::types::U256::from(val)), - data: Some(Bytes::from(call_data.encoded_call.to_vec())), - from: None, - gas_price: None, - value: None, - access_list: None, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - transaction_type: None, - }; - let result = web3.eth().call(req, Some(block_id)).boxed().await; + let mut req = TransactionRequest::default() + .input(TransactionInput::both(alloy::primitives::Bytes::from( + call_data.encoded_call.to_vec(), + ))) + .to(alloy::primitives::Address::from( + call_data.address.as_fixed_bytes(), + )); + + if let Some(gas) = gas { + req = req.gas_limit(gas as u64); + } + + let result = alloy.call(req).block(alloy_block_id).await; match result { Ok(bytes) => Ok(call::Retval::Value(scalar::Bytes::from(bytes))), diff --git a/graph/src/data/store/scalar/bytes.rs b/graph/src/data/store/scalar/bytes.rs index 585b548f931..2ae4a0b7165 100644 --- a/graph/src/data/store/scalar/bytes.rs +++ b/graph/src/data/store/scalar/bytes.rs @@ -123,3 +123,9 @@ impl FromSql for Bytes { as FromSql>::from_sql(value).map(Bytes::from) } } + +impl From for Bytes { + fn from(bytes: alloy::primitives::Bytes) -> Bytes { + Bytes::from(bytes.as_ref()) + } +} From d9c4ecd269885d202322a0b2fae26ff1f8a9fe84 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 19 Jun 2025 17:01:59 +0530 Subject: [PATCH 22/44] graph, chain/ethereum: migrate ContractCall to use alloy address --- chain/ethereum/src/ethereum_adapter.rs | 4 +--- chain/ethereum/src/runtime/runtime_adapter.rs | 3 +-- graph/src/cheap_clone.rs | 1 + graph/src/data/store/ethereum.rs | 4 ++-- graph/src/data_source/common.rs | 4 ++-- store/test-store/tests/postgres/chain_head.rs | 8 +++++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index e1e522a6da0..374ae3aba9c 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -615,9 +615,7 @@ impl EthereumAdapter { .input(TransactionInput::both(alloy::primitives::Bytes::from( call_data.encoded_call.to_vec(), ))) - .to(alloy::primitives::Address::from( - call_data.address.as_fixed_bytes(), - )); + .to(call_data.address); if let Some(gas) = gas { req = req.gas_limit(gas as u64); diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index 291042cb193..e5f984e5300 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -16,7 +16,6 @@ use graph::data::store::scalar::BigInt; use graph::data::subgraph::API_VERSION_0_0_9; use graph::data_source; use graph::data_source::common::{ContractCall, MappingABI}; -use graph::prelude::web3::types::Address; use graph::runtime::gas::Gas; use graph::runtime::{AscIndexId, IndexForAscTypeId}; use graph::slog::debug; @@ -390,7 +389,7 @@ fn eth_call( #[derive(Clone, Debug)] pub struct UnresolvedContractCall { pub contract_name: String, - pub contract_address: Address, + pub contract_address: alloy::primitives::Address, pub function_name: String, pub function_signature: Option, pub function_args: Vec, diff --git a/graph/src/cheap_clone.rs b/graph/src/cheap_clone.rs index 0d894d84434..93ebca27c39 100644 --- a/graph/src/cheap_clone.rs +++ b/graph/src/cheap_clone.rs @@ -119,3 +119,4 @@ cheap_clone_is_copy!( std::time::Duration ); cheap_clone_is_copy!(web3::types::Address); +cheap_clone_is_copy!(alloy::primitives::Address); diff --git a/graph/src/data/store/ethereum.rs b/graph/src/data/store/ethereum.rs index ae39f1ffcbc..263389c1dfb 100644 --- a/graph/src/data/store/ethereum.rs +++ b/graph/src/data/store/ethereum.rs @@ -104,7 +104,7 @@ pub mod call { /// on the call's return value #[derive(Debug, Clone, CheapClone)] pub struct Request { - pub address: web3::types::Address, + pub address: alloy::primitives::Address, pub encoded_call: Arc, /// The index is set by the caller and is used to identify the /// request in related data structures that the caller might have @@ -112,7 +112,7 @@ pub mod call { } impl Request { - pub fn new(address: web3::types::Address, encoded_call: Vec, index: u32) -> Self { + pub fn new(address: alloy::primitives::Address, encoded_call: Vec, index: u32) -> Self { Request { address, encoded_call: Arc::new(Bytes::from(encoded_call)), diff --git a/graph/src/data_source/common.rs b/graph/src/data_source/common.rs index bd6eecfe05a..84347f3b125 100644 --- a/graph/src/data_source/common.rs +++ b/graph/src/data_source/common.rs @@ -643,7 +643,7 @@ impl DeclaredCall { ( ContractCall { contract_name: self.contract_name, - address: self.address, + address: alloy::primitives::Address::from(self.address.as_fixed_bytes()), block_ptr, function: self.function, args: self.args, @@ -656,7 +656,7 @@ impl DeclaredCall { #[derive(Clone, Debug)] pub struct ContractCall { pub contract_name: String, - pub address: Address, + pub address: alloy::primitives::Address, pub block_ptr: BlockPtr, pub function: abi::Function, pub args: Vec, diff --git a/store/test-store/tests/postgres/chain_head.rs b/store/test-store/tests/postgres/chain_head.rs index cf501f1438f..8a09b845392 100644 --- a/store/test-store/tests/postgres/chain_head.rs +++ b/store/test-store/tests/postgres/chain_head.rs @@ -9,11 +9,11 @@ use graph::futures03::executor; use std::future::Future; use std::sync::Arc; +use graph::cheap_clone::CheapClone; use graph::prelude::web3::types::H256; +use graph::prelude::{alloy, serde_json as json, EthereumBlock}; use graph::prelude::{anyhow::anyhow, anyhow::Error}; -use graph::prelude::{serde_json as json, EthereumBlock}; use graph::prelude::{BlockNumber, QueryStoreManager, QueryTarget}; -use graph::{cheap_clone::CheapClone, prelude::web3::types::H160}; use graph::{components::store::BlockStore as _, prelude::DeploymentHash}; use graph::{ components::store::ChainHeadStore as _, components::store::ChainStore as _, @@ -430,7 +430,9 @@ fn eth_call_cache() { call::Retval::Value(Bytes::from(value)) } - let address = H160([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); + let address = alloy::primitives::Address::from_slice(&[ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + ]); let call: [u8; 6] = [1, 2, 3, 4, 5, 6]; let return_value: [u8; 3] = [7, 8, 9]; From e295cfdaf9927497bc63264c0cbb9d3d28e26b8b Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 14:29:29 +0530 Subject: [PATCH 23/44] graph: Add util functions for alloy web3 conversions --- graph/src/lib.rs | 4 ++ graph/src/util/conversions.rs | 100 ++++++++++++++++++++++++++++++++++ graph/src/util/mod.rs | 3 + 3 files changed, 107 insertions(+) create mode 100644 graph/src/util/conversions.rs diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 2c511c411d5..fbaaed12d75 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -176,6 +176,10 @@ pub mod prelude { }; pub use crate::log::split::split_logger; pub use crate::util::cache_weight::CacheWeight; + pub use crate::util::conversions::{ + alloy_address_to_h160, alloy_address_to_web3_address, alloy_log_to_web3_log, b256_to_h256, + h160_to_alloy_address, h256_to_b256, web3_address_to_alloy_address, + }; pub use crate::util::futures::{retry, TimeoutError}; pub use crate::util::stats::MovingStats; diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs new file mode 100644 index 00000000000..62c8cbf56a3 --- /dev/null +++ b/graph/src/util/conversions.rs @@ -0,0 +1,100 @@ +use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; +use crate::prelude::alloy::rpc::types::Log as AlloyLog; +/// Type conversion utilities between web3 and alloy types +use crate::prelude::web3::types::{Address as Web3Address, Log as Web3Log, H160, H256, U256, U64}; + +/// Converts web3 H256 to alloy B256 +pub fn h256_to_b256(h: H256) -> B256 { + B256::from_slice(h.as_bytes()) +} + +/// Converts alloy B256 to web3 H256 +pub fn b256_to_h256(b: B256) -> H256 { + H256::from_slice(b.as_slice()) +} + +/// Converts web3 H160 to alloy Address +pub fn h160_to_alloy_address(h: H160) -> AlloyAddress { + AlloyAddress::from_slice(h.as_bytes()) +} + +/// Converts alloy Address to web3 H160 +pub fn alloy_address_to_h160(addr: AlloyAddress) -> H160 { + H160::from_slice(addr.as_slice()) +} + +/// Converts web3 Address to alloy Address +pub fn web3_address_to_alloy_address(addr: Web3Address) -> AlloyAddress { + h160_to_alloy_address(addr) +} + +/// Converts alloy Address to web3 Address +pub fn alloy_address_to_web3_address(addr: AlloyAddress) -> Web3Address { + alloy_address_to_h160(addr) +} + +/// Converts alloy Log to web3 Log +pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { + Web3Log { + address: alloy_address_to_h160(log.address()), + topics: log.topics().iter().map(|t| b256_to_h256(*t)).collect(), + data: log.data().data.clone().into(), + block_hash: log.block_hash.map(b256_to_h256), + block_number: log.block_number.map(|n| U64::from(n)), + transaction_hash: log.transaction_hash.map(b256_to_h256), + transaction_index: log.transaction_index.map(|i| U64::from(i)), + log_index: log.log_index.map(|i| U256::from(i)), + transaction_log_index: None, // alloy Log doesn't have transaction_log_index + log_type: None, // alloy Log doesn't have log_type + removed: Some(log.removed), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_h256_to_b256_conversion() { + let h = H256::from([1u8; 32]); + let b = h256_to_b256(h); + assert_eq!(b.as_slice(), &[1u8; 32]); + } + + #[test] + fn test_b256_to_h256_conversion() { + let b = B256::from([2u8; 32]); + let h = b256_to_h256(b); + assert_eq!(h.as_bytes(), &[2u8; 32]); + } + + #[test] + fn test_round_trip_conversion() { + let original_h = H256::from([42u8; 32]); + let b = h256_to_b256(original_h); + let converted_h = b256_to_h256(b); + assert_eq!(original_h, converted_h); + } + + #[test] + fn test_h160_to_alloy_address_conversion() { + let h = H160::from([1u8; 20]); + let addr = h160_to_alloy_address(h); + assert_eq!(addr.as_slice(), &[1u8; 20]); + } + + #[test] + fn test_alloy_address_to_h160_conversion() { + let addr = AlloyAddress::from([2u8; 20]); + let h = alloy_address_to_h160(addr); + assert_eq!(h.as_bytes(), &[2u8; 20]); + } + + #[test] + fn test_address_round_trip_conversion() { + let original_h = H160::from([42u8; 20]); + let addr = h160_to_alloy_address(original_h); + let converted_h = alloy_address_to_h160(addr); + assert_eq!(original_h, converted_h); + } +} diff --git a/graph/src/util/mod.rs b/graph/src/util/mod.rs index 4cdf52a82a5..ea72fbee1dd 100644 --- a/graph/src/util/mod.rs +++ b/graph/src/util/mod.rs @@ -35,3 +35,6 @@ pub mod monitored; pub mod intern; pub mod herd_cache; + +/// Type conversion utilities between web3 and alloy types +pub mod conversions; From 0728e7c10707467e24a8590908f3535e4962d164 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 14:52:20 +0530 Subject: [PATCH 24/44] checkpoint --- chain/ethereum/src/adapter.rs | 212 ++++++++++++++++++++++--- chain/ethereum/src/ethereum_adapter.rs | 74 +++++---- 2 files changed, 227 insertions(+), 59 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index ee61da770a9..7cc01286a60 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -20,6 +20,7 @@ use tiny_keccak::keccak256; use web3::types::{Address, Log, H256}; use graph::prelude::*; +use graph::prelude::{alloy_address_to_h160, b256_to_h256}; use graph::{ blockchain as bc, components::metrics::{CounterVec, GaugeVec, HistogramVec}, @@ -92,6 +93,67 @@ impl EventSignatureWithTopics { } } +/// `EventSignatureWithTopics` is used to match events with +/// indexed arguments when they are defined in the subgraph +/// manifest. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct EventSignatureWithTopicsForAlloy { + pub address: Option, + pub signature: alloy::primitives::B256, + pub topic1: Option>, + pub topic2: Option>, + pub topic3: Option>, +} + +impl EventSignatureWithTopicsForAlloy { + #[allow(dead_code)] + pub fn new( + address: Option, + signature: alloy::primitives::B256, + topic1: Option>, + topic2: Option>, + topic3: Option>, + ) -> Self { + EventSignatureWithTopicsForAlloy { + address, + signature, + topic1, + topic2, + topic3, + } + } + + /// Checks if an event matches the `EventSignatureWithTopics` + /// If self.address is None, it's considered a wildcard match. + /// Otherwise, it must match the provided address. + /// It must also match the topics if they are Some + #[allow(dead_code)] + pub fn matches( + &self, + address: Option<&alloy::primitives::Address>, + sig: alloy::primitives::B256, + topics: &Vec, + ) -> bool { + // If self.address is None, it's considered a wildcard match. Otherwise, it must match the provided address. + let address_matches = match self.address { + Some(ref self_addr) => address == Some(self_addr), + None => true, // self.address is None, so it matches any address. + }; + + address_matches + && self.signature == sig + && self.topic1.as_ref().map_or(true, |t1| { + topics.get(1).map_or(false, |topic| t1.contains(topic)) + }) + && self.topic2.as_ref().map_or(true, |t2| { + topics.get(2).map_or(false, |topic| t2.contains(topic)) + }) + && self.topic3.as_ref().map_or(true, |t3| { + topics.get(3).map_or(false, |topic| t3.contains(topic)) + }) + } +} + #[derive(Error, Debug)] pub enum EthereumRpcError { #[error("call error: {0}")] @@ -147,15 +209,36 @@ enum LogFilterNode { /// Corresponds to an `eth_getLogs` call. #[derive(Clone, Debug)] pub struct EthGetLogsFilter { - pub contracts: Vec
, - pub event_signatures: Vec, - pub topic1: Option>, - pub topic2: Option>, - pub topic3: Option>, + pub contracts: Vec, + pub event_signatures: Vec, + pub topic1: Option>, + pub topic2: Option>, + pub topic3: Option>, } impl EthGetLogsFilter { - fn from_contract(address: Address) -> Self { + /// Convert to alloy Filter for the given block range + pub fn to_alloy_filter(&self, from: BlockNumber, to: BlockNumber) -> alloy::rpc::types::Filter { + let mut filter_builder = alloy::rpc::types::Filter::new() + .from_block(alloy::rpc::types::BlockNumberOrTag::Number(from as u64)) + .to_block(alloy::rpc::types::BlockNumberOrTag::Number(to as u64)) + .address(self.contracts.clone()) + .event_signature(self.event_signatures.clone()); + + if let Some(ref topic1) = self.topic1 { + filter_builder = filter_builder.topic1(topic1.clone()); + } + if let Some(ref topic2) = self.topic2 { + filter_builder = filter_builder.topic2(topic2.clone()); + } + if let Some(ref topic3) = self.topic3 { + filter_builder = filter_builder.topic3(topic3.clone()); + } + + filter_builder + } + + fn from_contract(address: alloy::primitives::Address) -> Self { EthGetLogsFilter { contracts: vec![address], event_signatures: vec![], @@ -165,7 +248,7 @@ impl EthGetLogsFilter { } } - fn from_event(event: EventSignature) -> Self { + fn from_event(event: alloy::primitives::B256) -> Self { EthGetLogsFilter { contracts: vec![], event_signatures: vec![event], @@ -175,7 +258,7 @@ impl EthGetLogsFilter { } } - fn from_event_with_topics(event: EventSignatureWithTopics) -> Self { + fn from_event_with_topics(event: EventSignatureWithTopicsForAlloy) -> Self { EthGetLogsFilter { contracts: event.address.map_or(vec![], |a| vec![a]), event_signatures: vec![event.signature], @@ -205,7 +288,7 @@ impl fmt::Display for EthGetLogsFilter { }; // Helper to format topics as strings - let format_topics = |topics: &Option>| -> String { + let format_topics = |topics: &Option>| -> String { topics.as_ref().map_or_else( || "None".to_string(), |ts| { @@ -351,11 +434,11 @@ impl From for Vec { }| LogFilter { addresses: contracts .iter() - .map(|addr| addr.to_fixed_bytes().to_vec()) + .map(|addr| addr.to_vec()) .collect_vec(), event_signatures: event_signatures .iter() - .map(|sig| sig.to_fixed_bytes().to_vec()) + .map(|sig| sig.to_vec()) .collect_vec(), }, ) @@ -431,6 +514,55 @@ impl EthereumLogFilter { false } + /// Similar to [`matches`], checks if a transaction receipt is required for this log filter. + pub fn requires_transaction_receipt_alloy( + &self, + event_signature: &alloy::primitives::B256, + contract_address: Option<&alloy::primitives::Address>, + topics: &[alloy::primitives::B256], + ) -> bool { + // Check for wildcard events first. + if self.wildcard_events.get(&b256_to_h256(*event_signature)) == Some(&true) { + return true; + } + + // Next, check events with topic filters. + if self + .events_with_topic_filters + .iter() + .any(|(event_with_topics, &requires_receipt)| { + requires_receipt + && event_with_topics.matches( + contract_address + .map(|addr| alloy_address_to_h160(*addr)) + .as_ref(), + b256_to_h256(*event_signature), + &topics.iter().map(|t| b256_to_h256(*t)).collect(), + ) + }) + { + return true; + } + + // Finally, check the contracts_and_events_graph if a contract address is specified. + if let Some(address) = contract_address { + let contract_node = LogFilterNode::Contract(alloy_address_to_h160(*address)); + let event_node = LogFilterNode::Event(b256_to_h256(*event_signature)); + + // Directly iterate over all edges and return true if a matching edge that requires a receipt is found. + for (s, t, &r) in self.contracts_and_events_graph.all_edges() { + if r && ((s == contract_node && t == event_node) + || (t == contract_node && s == event_node)) + { + return true; + } + } + } + + // If none of the conditions above match, return false. + false + } + pub fn from_data_sources<'a>(iter: impl IntoIterator) -> Self { let mut this = EthereumLogFilter::default(); for ds in iter { @@ -530,18 +662,33 @@ impl EthereumLogFilter { let mut filters = Vec::new(); // Start with the wildcard event filters. - filters.extend( - self.wildcard_events - .into_keys() - .map(EthGetLogsFilter::from_event), - ); + filters.extend(self.wildcard_events.into_keys().map(|h256_event| { + let alloy_event = alloy::primitives::B256::from_slice(h256_event.as_bytes()); + EthGetLogsFilter::from_event(alloy_event) + })); // Handle events with topic filters. filters.extend( self.events_with_topic_filters .into_iter() .map(|(event_with_topics, _)| { - EthGetLogsFilter::from_event_with_topics(event_with_topics) + // Convert EventSignatureWithTopics to EventSignatureWithTopicsForAlloy + let alloy_event = EventSignatureWithTopicsForAlloy { + address: event_with_topics + .address + .map(|addr| h160_to_alloy_address(addr)), + signature: h256_to_b256(event_with_topics.signature), + topic1: event_with_topics + .topic1 + .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), + topic2: event_with_topics + .topic2 + .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), + topic3: event_with_topics + .topic3 + .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), + }; + EthGetLogsFilter::from_event_with_topics(alloy_event) }), ); @@ -572,8 +719,14 @@ impl EthereumLogFilter { // If there are edges, there are vertexes. let max_vertex = g.nodes().max_by_key(|&n| g.neighbors(n).count()).unwrap(); let mut filter = match max_vertex { - LogFilterNode::Contract(address) => EthGetLogsFilter::from_contract(address), - LogFilterNode::Event(event_sig) => EthGetLogsFilter::from_event(event_sig), + LogFilterNode::Contract(address) => { + let alloy_address = alloy::primitives::Address::from_slice(address.as_bytes()); + EthGetLogsFilter::from_contract(alloy_address) + } + LogFilterNode::Event(event_sig) => { + let alloy_event = alloy::primitives::B256::from_slice(event_sig.as_bytes()); + EthGetLogsFilter::from_event(alloy_event) + } }; for neighbor in g.neighbors(max_vertex) { match neighbor { @@ -584,9 +737,14 @@ impl EthereumLogFilter { push_filter(filter); filter = EthGetLogsFilter::from_event(event); } - filter.contracts.push(address); + let alloy_address = + alloy::primitives::Address::from_slice(address.as_bytes()); + filter.contracts.push(alloy_address); + } + LogFilterNode::Event(event_sig) => { + let alloy_event = alloy::primitives::B256::from_slice(event_sig.as_bytes()); + filter.event_signatures.push(alloy_event); } - LogFilterNode::Event(event_sig) => filter.event_signatures.push(event_sig), } } @@ -1775,18 +1933,22 @@ fn complete_log_filter() { // Test a few combinations of complete graphs. for i in [1, 2] { - let events: BTreeSet<_> = (0..i).map(H256::from_low_u64_le).collect(); + let events: BTreeSet<_> = (0..i) + .map(|n| alloy::primitives::B256::from([n as u8; 32])) + .collect(); for j in [1, 1000, 2000, 3000] { - let contracts: BTreeSet<_> = (0..j).map(Address::from_low_u64_le).collect(); + let contracts: BTreeSet<_> = (0..j) + .map(|n| alloy::primitives::Address::from([n as u8; 20])) + .collect(); // Construct the complete bipartite graph with i events and j contracts. let mut contracts_and_events_graph = GraphMap::new(); for &contract in &contracts { for &event in &events { contracts_and_events_graph.add_edge( - LogFilterNode::Contract(contract), - LogFilterNode::Event(event), + LogFilterNode::Contract(alloy_address_to_h160(contract)), + LogFilterNode::Event(b256_to_h256(event)), false, ); } diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 374ae3aba9c..31fcd21c510 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -21,7 +21,9 @@ use graph::futures03::{ }; use graph::prelude::alloy; use graph::prelude::alloy::rpc::types::{TransactionInput, TransactionRequest}; +use graph::prelude::alloy::transports::RpcError; use graph::prelude::tokio::try_join; +use graph::prelude::{alloy_log_to_web3_log, b256_to_h256}; use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; @@ -32,7 +34,7 @@ use graph::{ async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, web3::{ self, - types::{BlockId, Filter, FilterBuilder, Log, Transaction, TransactionReceipt, H256}, + types::{BlockId, Transaction, TransactionReceipt, H256}, }, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, TimeoutError, @@ -52,6 +54,7 @@ use std::pin::Pin; use std::sync::Arc; use std::time::Instant; +use crate::adapter::EthGetLogsFilter; use crate::adapter::EthereumRpcError; use crate::adapter::ProviderStatus; use crate::call_helper::interpret_eth_call_error; @@ -62,9 +65,8 @@ use crate::NodeCapabilities; use crate::TriggerFilter; use crate::{ adapter::{ - ContractCallError, EthGetLogsFilter, EthereumAdapter as EthereumAdapterTrait, - EthereumBlockFilter, EthereumCallFilter, EthereumLogFilter, ProviderEthRpcMetrics, - SubgraphEthRpcMetrics, + ContractCallError, EthereumAdapter as EthereumAdapterTrait, EthereumBlockFilter, + EthereumCallFilter, EthereumLogFilter, ProviderEthRpcMetrics, SubgraphEthRpcMetrics, }, transport::Transport, trigger::{EthereumBlockTriggerType, EthereumTrigger}, @@ -305,6 +307,7 @@ impl EthereumAdapter { result } + /// Alloy-exclusive version of logs_with_sigs using alloy types and methods async fn logs_with_sigs( &self, logger: Logger, @@ -313,19 +316,24 @@ impl EthereumAdapter { to: BlockNumber, filter: Arc, too_many_logs_fingerprints: &'static [&'static str], - ) -> Result, TimeoutError> { + ) -> Result< + Vec, + TimeoutError>, + > { assert!(!self.call_only); let eth_adapter = self.clone(); let retry_log_message = format!("eth_getLogs RPC call for block range: [{}..{}]", from, to); retry(retry_log_message, &logger) .redact_log_urls(true) - .when(move |res: &Result<_, web3::error::Error>| match res { - Ok(_) => false, - Err(e) => !too_many_logs_fingerprints - .iter() - .any(|f| e.to_string().contains(f)), - }) + .when( + move |res: &Result<_, RpcError>| match res { + Ok(_) => false, + Err(e) => !too_many_logs_fingerprints + .iter() + .any(|f| e.to_string().contains(f)), + }, + ) .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { @@ -337,21 +345,10 @@ impl EthereumAdapter { async move { let start = Instant::now(); - // Create a log filter - let log_filter: Filter = FilterBuilder::default() - .from_block(from.into()) - .to_block(to.into()) - .address(filter.contracts.clone()) - .topics( - Some(filter.event_signatures.clone()), - filter.topic1.clone(), - filter.topic2.clone(), - filter.topic3.clone(), - ) - .build(); - // Request logs from client - let result = eth_adapter.web3.eth().logs(log_filter).boxed().await; + let alloy_filter = filter.to_alloy_filter(from, to); + + let result = eth_adapter.alloy.get_logs(&alloy_filter).await; let elapsed = start.elapsed().as_secs_f64(); provider_metrics.observe_request(elapsed, "eth_getLogs", &provider); subgraph_metrics.observe_request(elapsed, "eth_getLogs", &provider); @@ -425,7 +422,7 @@ impl EthereumAdapter { from: BlockNumber, to: BlockNumber, filter: EthGetLogsFilter, - ) -> DynTryFuture<'static, Vec, Error> { + ) -> DynTryFuture<'static, Vec, Error> { // Codes returned by Ethereum node providers if an eth_getLogs request is too heavy. const TOO_MANY_LOGS_FINGERPRINTS: &[&str] = &[ "ServerError(-32005)", // Infura @@ -832,7 +829,7 @@ impl EthereumAdapter { from: BlockNumber, to: BlockNumber, log_filter: EthereumLogFilter, - ) -> DynTryFuture<'static, Vec, Error> { + ) -> DynTryFuture<'static, Vec, Error> { let eth: Self = self.cheap_clone(); let logger = logger.clone(); @@ -2383,8 +2380,12 @@ async fn get_logs_and_transactions( .iter() .filter(|_| unified_api_version.equal_or_greater_than(&API_VERSION_0_0_7)) .filter(|log| { - if let Some(signature) = log.topics.first() { - log_filter.requires_transaction_receipt(signature, Some(&log.address), &log.topics) + if let Some(signature) = log.topics().first() { + log_filter.requires_transaction_receipt_alloy( + signature, + Some(&log.address()), + &log.topics(), + ) } else { false } @@ -2401,7 +2402,9 @@ async fn get_logs_and_transactions( .fold( HashMap::>::new(), |mut acc, (block_hash, txn_hash)| { - acc.entry(block_hash).or_default().insert(txn_hash); + acc.entry(b256_to_h256(block_hash)) + .or_default() + .insert(b256_to_h256(txn_hash)); acc }, ); @@ -2418,10 +2421,13 @@ async fn get_logs_and_transactions( // Associate each log with its receipt, when possible let mut log_triggers = Vec::new(); for log in logs.into_iter() { - let optional_receipt = log - .transaction_hash - .and_then(|txn| transaction_receipts_by_hash.get(&txn).cloned()); - let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(log), optional_receipt)); + let optional_receipt = log.transaction_hash.and_then(|txn| { + transaction_receipts_by_hash + .get(&b256_to_h256(txn)) + .cloned() + }); + let web3_log = alloy_log_to_web3_log(log); + let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(web3_log), optional_receipt)); log_triggers.push(value); } From fb892396e30a1d41ef540934589f56b7881ce132 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 17:38:50 +0530 Subject: [PATCH 25/44] graph: add alloy_transaction_receipt_to_web3_transaction_receipt to conversions --- graph/src/util/conversions.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 62c8cbf56a3..ae59032a0a9 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -1,14 +1,21 @@ +use std::sync::Arc; + use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; -use crate::prelude::alloy::rpc::types::Log as AlloyLog; +use crate::prelude::alloy::rpc::types::{ + Block as AlloyBlock, Log as AlloyLog, TransactionReceipt as AlloyTransactionReceipt, +}; /// Type conversion utilities between web3 and alloy types -use crate::prelude::web3::types::{Address as Web3Address, Log as Web3Log, H160, H256, U256, U64}; +use crate::prelude::web3::types::{ + Address as Web3Address, Block as Web3Block, Log as Web3Log, Transaction as Web3Transaction, + TransactionReceipt as Web3TransactionReceipt, H160, H256, U256, U64, +}; -/// Converts web3 H256 to alloy B256 +/// Converts H256 to alloy B256 pub fn h256_to_b256(h: H256) -> B256 { B256::from_slice(h.as_bytes()) } -/// Converts alloy B256 to web3 H256 +/// Converts alloy B256 to H256 pub fn b256_to_h256(b: B256) -> H256 { H256::from_slice(b.as_slice()) } @@ -50,6 +57,26 @@ pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { } } +pub fn alloy_transaction_receipt_to_web3_transaction_receipt( + _receipt: Arc, +) -> Arc { + unimplemented!("TransactionReceipt conversion not yet implemented - will be done when needed") +} + +/// Converts alloy Block to web3 Block +pub fn alloy_block_to_web3_block(_block: AlloyBlock) -> Web3Block { + unimplemented!( + "Block conversion from alloy to web3 not yet implemented - will be done when needed" + ) +} + +/// Converts web3 Block to alloy Block +pub fn web3_block_to_alloy_block(_block: Web3Block) -> AlloyBlock { + unimplemented!( + "Block conversion from web3 to alloy not yet implemented - will be done when needed" + ) +} + #[cfg(test)] mod tests { use super::*; From 6d1fdc6ab576ef187993bce5e022cd2c4eacc939 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 17:39:44 +0530 Subject: [PATCH 26/44] receipts checkpoint --- chain/ethereum/src/ethereum_adapter.rs | 309 +++++++++++--------- graph/src/blockchain/mod.rs | 7 +- graph/src/components/transaction_receipt.rs | 18 ++ graph/src/lib.rs | 5 +- graph/src/util/conversions.rs | 15 + 5 files changed, 207 insertions(+), 147 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 31fcd21c510..14831f6c13d 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -20,8 +20,12 @@ use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; use graph::prelude::alloy; +use graph::prelude::alloy::primitives::B256; use graph::prelude::alloy::rpc::types::{TransactionInput, TransactionRequest}; use graph::prelude::alloy::transports::RpcError; + +use graph::prelude::alloy_transaction_receipt_to_web3_transaction_receipt; +use graph::prelude::h256_to_b256; use graph::prelude::tokio::try_join; use graph::prelude::{alloy_log_to_web3_log, b256_to_h256}; use graph::slog::o; @@ -32,10 +36,7 @@ use graph::{ prelude::{ anyhow::{self, anyhow, bail, ensure, Context}, async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, - web3::{ - self, - types::{BlockId, Transaction, TransactionReceipt, H256}, - }, + web3::types::{BlockId, Transaction, H256}, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, TimeoutError, }, @@ -43,7 +44,6 @@ use graph::{ use graph::{ components::ethereum::*, prelude::web3::api::Web3, - prelude::web3::transports::Batch, prelude::web3::types::{Trace, TraceFilter, TraceFilterBuilder, H160}, }; use itertools::Itertools; @@ -256,8 +256,8 @@ impl EthereumAdapter { // cached. The result is not used for anything critical, so it is fine to be lazy. async fn check_block_receipt_support_and_update_cache( &self, - web3: Arc>, - block_hash: H256, + alloy: Arc, + block_hash: B256, supports_eip_1898: bool, call_only: bool, logger: Logger, @@ -274,7 +274,7 @@ impl EthereumAdapter { info!(logger, "Checking eth_getBlockReceipts support"); let result = timeout( ENV_VARS.block_receipts_check_timeout, - check_block_receipt_support(web3, block_hash, supports_eip_1898, call_only), + check_block_receipt_support(alloy, block_hash, supports_eip_1898, call_only), ) .await; @@ -1277,7 +1277,7 @@ impl EthereumAdapterTrait for EthereumAdapter { logger: &Logger, block: LightEthereumBlock, ) -> Result { - let web3 = Arc::clone(&self.web3); + let alloy = self.alloy.clone(); let logger = logger.clone(); let block_hash = block.hash.expect("block is missing block hash"); @@ -1294,20 +1294,31 @@ impl EthereumAdapterTrait for EthereumAdapter { let supports_block_receipts = self .check_block_receipt_support_and_update_cache( - web3.clone(), - block_hash, + alloy.clone(), + h256_to_b256(block_hash), self.supports_eip_1898, self.call_only, logger.clone(), ) .await; - fetch_receipts_with_retry(web3, hashes, block_hash, logger, supports_block_receipts) - .await - .map(|transaction_receipts| EthereumBlock { - block: Arc::new(block), - transaction_receipts, - }) + let hashes_b256 = hashes.iter().map(|hash| h256_to_b256(*hash)).collect(); + let block_hash_b256 = h256_to_b256(block_hash); + fetch_receipts_with_retry( + alloy, + hashes_b256, + block_hash_b256, + logger, + supports_block_receipts, + ) + .await + .map(|transaction_receipts| EthereumBlock { + block: Arc::new(block), + transaction_receipts: transaction_receipts + .into_iter() + .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)) + .collect(), + }) } async fn get_balance( @@ -1951,9 +1962,9 @@ pub(crate) fn parse_block_triggers( async fn fetch_receipt_from_ethereum_client( eth: &EthereumAdapter, - transaction_hash: &H256, -) -> anyhow::Result { - match eth.web3.eth().transaction_receipt(*transaction_hash).await { + transaction_hash: B256, +) -> anyhow::Result { + match eth.alloy.get_transaction_receipt(transaction_hash).await { Ok(Some(receipt)) => Ok(receipt), Ok(None) => bail!("Could not find transaction receipt"), Err(error) => bail!("Failed to fetch transaction receipt: {}", error), @@ -2041,7 +2052,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions( let futures = transactions_without_receipt .iter() .map(|transaction| async move { - fetch_receipt_from_ethereum_client(eth, &transaction.hash) + fetch_receipt_from_ethereum_client(eth, h256_to_b256(transaction.hash)) .await .map(|receipt| (transaction, receipt)) }); @@ -2103,11 +2114,11 @@ async fn filter_call_triggers_from_unsuccessful_transactions( /// Deprecated. Wraps the [`fetch_transaction_receipts_in_batch`] in a retry loop. async fn fetch_transaction_receipts_in_batch_with_retry( - web3: Arc>, - hashes: Vec, - block_hash: H256, + alloy: Arc, + hashes: Vec, + block_hash: B256, logger: Logger, -) -> Result>, IngestorError> { +) -> Result>, IngestorError> { let retry_log_message = format!( "batch eth_getTransactionReceipt RPC call for block {:?}", block_hash @@ -2118,51 +2129,83 @@ async fn fetch_transaction_receipts_in_batch_with_retry( .no_logging() .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); let hashes = hashes.clone(); let logger = logger.cheap_clone(); - fetch_transaction_receipts_in_batch(web3, hashes, block_hash, logger).boxed() + fetch_transaction_receipts_in_batch(alloy, hashes, block_hash, logger).boxed() }) .await .map_err(|_timeout| anyhow!(block_hash).into()) } -/// Deprecated. Attempts to fetch multiple transaction receipts in a batching contex. +/// Deprecated. Attempts to fetch multiple transaction receipts in a batching context. async fn fetch_transaction_receipts_in_batch( - web3: Arc>, - hashes: Vec, - block_hash: H256, + alloy: Arc, + hashes: Vec, + block_hash: B256, logger: Logger, -) -> Result>, IngestorError> { - let batching_web3 = Web3::new(Batch::new(web3.transport().clone())); - let eth = batching_web3.eth(); - let receipt_futures = hashes - .into_iter() - .map(move |hash| { - let logger = logger.cheap_clone(); - eth.transaction_receipt(hash) - .map_err(IngestorError::from) - .and_then(move |some_receipt| async move { - resolve_transaction_receipt(some_receipt, hash, block_hash, logger) - }) - }) - .collect::>(); +) -> Result>, IngestorError> { + // Use the batch method to get all receipts at once + let receipts = batch_get_transaction_receipts(alloy, hashes.clone()) + .await + .map_err(|e| { + IngestorError::Unknown(anyhow::anyhow!("Batch receipt fetch failed: {}", e)) + })?; + + let mut result = Vec::new(); + for receipt in receipts { + if let Some(receipt) = receipt { + // Validate the receipt before adding it + let validated_receipt = resolve_transaction_receipt( + Some(receipt), + hashes[0], + block_hash, + logger.cheap_clone(), + )?; + result.push(Arc::new(validated_receipt)); + } + } - batching_web3.transport().submit_batch().await?; + Ok(result) +} - let mut collected = vec![]; - for receipt in receipt_futures.into_iter() { - collected.push(Arc::new(receipt.await?)) +async fn batch_get_transaction_receipts( + provider: Arc, + tx_hashes: Vec, +) -> Result>, Box> { + let mut batch = alloy::rpc::client::BatchRequest::new(provider.client()); + let mut receipt_futures = Vec::new(); + + // Add all receipt requests to batch + for tx_hash in &tx_hashes { + let receipt_future = batch + .add_call::<(B256,), Option>( + "eth_getTransactionReceipt", + &(*tx_hash,), + )?; + receipt_futures.push(receipt_future); } - Ok(collected) + + // Execute batch + batch.send().await?; + + // Collect results in order + let mut results = Vec::new(); + for receipt_future in receipt_futures { + let receipt = receipt_future.await.unwrap_or(None); + results.push(receipt); + } + + Ok(results) } pub(crate) async fn check_block_receipt_support( - web3: Arc>, - block_hash: H256, + alloy: Arc, + block_hash: B256, supports_eip_1898: bool, call_only: bool, ) -> Result<(), Error> { + use alloy::rpc::types::BlockId; if call_only { return Err(anyhow!("Provider is call-only")); } @@ -2172,7 +2215,7 @@ pub(crate) async fn check_block_receipt_support( } // Fetch block receipts from the provider for the latest block. - let block_receipts_result = web3.eth().block_receipts(BlockId::Hash(block_hash)).await; + let block_receipts_result = alloy.get_block_receipts(BlockId::from(block_hash)).await; // Determine if the provider supports block receipts based on the fetched result. match block_receipts_result { @@ -2186,27 +2229,27 @@ pub(crate) async fn check_block_receipt_support( // based on whether block receipts are supported or individual transaction receipts // need to be fetched. async fn fetch_receipts_with_retry( - web3: Arc>, - hashes: Vec, - block_hash: H256, + alloy: Arc, + hashes: Vec, + block_hash: B256, logger: Logger, supports_block_receipts: bool, -) -> Result>, IngestorError> { +) -> Result>, IngestorError> { if supports_block_receipts { - return fetch_block_receipts_with_retry(web3, hashes, block_hash, logger).await; + return fetch_block_receipts_with_retry(alloy, hashes, block_hash, logger).await; } - fetch_individual_receipts_with_retry(web3, hashes, block_hash, logger).await + fetch_individual_receipts_with_retry(alloy, hashes, block_hash, logger).await } // Fetches receipts for each transaction in the block individually. async fn fetch_individual_receipts_with_retry( - web3: Arc>, - hashes: Vec, - block_hash: H256, + alloy: Arc, + hashes: Vec, + block_hash: B256, logger: Logger, -) -> Result>, IngestorError> { +) -> Result>, IngestorError> { if ENV_VARS.fetch_receipts_in_batches { - return fetch_transaction_receipts_in_batch_with_retry(web3, hashes, block_hash, logger) + return fetch_transaction_receipts_in_batch_with_retry(alloy, hashes, block_hash, logger) .await; } @@ -2215,7 +2258,7 @@ async fn fetch_individual_receipts_with_retry( let receipt_stream = hash_stream .map(move |tx_hash| { fetch_transaction_receipt_with_retry( - web3.cheap_clone(), + alloy.cheap_clone(), tx_hash, block_hash, logger.cheap_clone(), @@ -2223,19 +2266,20 @@ async fn fetch_individual_receipts_with_retry( }) .buffered(ENV_VARS.block_ingestor_max_concurrent_json_rpc_calls); - graph::tokio_stream::StreamExt::collect::>, IngestorError>>( - receipt_stream, - ) + graph::tokio_stream::StreamExt::collect::< + Result>, IngestorError>, + >(receipt_stream) .await } /// Fetches transaction receipts of all transactions in a block with `eth_getBlockReceipts` call. async fn fetch_block_receipts_with_retry( - web3: Arc>, - hashes: Vec, - block_hash: H256, + alloy: Arc, + hashes: Vec, + block_hash: B256, logger: Logger, -) -> Result>, IngestorError> { +) -> Result>, IngestorError> { + use graph::prelude::alloy::rpc::types::BlockId; let logger = logger.cheap_clone(); let retry_log_message = format!("eth_getBlockReceipts RPC call for block {:?}", block_hash); @@ -2244,7 +2288,7 @@ async fn fetch_block_receipts_with_retry( .redact_log_urls(true) .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || web3.eth().block_receipts(BlockId::Hash(block_hash)).boxed()) + .run(move || alloy.get_block_receipts(BlockId::from(block_hash)).boxed()) .await .map_err(|_timeout| -> IngestorError { anyhow!(block_hash).into() })?; @@ -2273,23 +2317,27 @@ async fn fetch_block_receipts_with_retry( } } -/// Retries fetching a single transaction receipt. +/// Retries fetching a single transaction receipt using alloy, then converts to web3 format. async fn fetch_transaction_receipt_with_retry( - web3: Arc>, - transaction_hash: H256, - block_hash: H256, + alloy: Arc, + transaction_hash: B256, + block_hash: B256, logger: Logger, -) -> Result, IngestorError> { +) -> Result, IngestorError> { let logger = logger.cheap_clone(); let retry_log_message = format!( "eth_getTransactionReceipt RPC call for transaction {:?}", transaction_hash ); + retry(retry_log_message, &logger) .redact_log_urls(true) .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || web3.eth().transaction_receipt(transaction_hash).boxed()) + .run(move || { + let alloy_clone = alloy.clone(); + async move { alloy_clone.get_transaction_receipt(transaction_hash).await }.boxed() + }) .await .map_err(|_timeout| anyhow!(block_hash).into()) .and_then(move |some_receipt| { @@ -2299,11 +2347,11 @@ async fn fetch_transaction_receipt_with_retry( } fn resolve_transaction_receipt( - transaction_receipt: Option, - transaction_hash: H256, - block_hash: H256, + transaction_receipt: Option, + transaction_hash: B256, + block_hash: B256, logger: Logger, -) -> Result { +) -> Result { match transaction_receipt { // A receipt might be missing because the block was uncled, and the transaction never // made it back into the main chain. @@ -2331,7 +2379,7 @@ fn resolve_transaction_receipt( // considers this block to be in the main chain. Nothing we can do from here except // give up trying to ingest this block. There is no way to get the transaction // receipt from this block. - Err(IngestorError::BlockUnavailable(block_hash)) + Err(IngestorError::BlockUnavailable(b256_to_h256(block_hash))) } else { Ok(receipt) } @@ -2376,7 +2424,7 @@ async fn get_logs_and_transactions( // Not all logs have associated transaction hashes, nor do all triggers require them. // We also restrict receipts retrieval for some api versions. - let transaction_hashes_by_block: HashMap> = logs + let transaction_hashes_by_block: HashMap> = logs .iter() .filter(|_| unified_api_version.equal_or_greater_than(&API_VERSION_0_0_7)) .filter(|log| { @@ -2400,11 +2448,9 @@ async fn get_logs_and_transactions( } }) .fold( - HashMap::>::new(), + HashMap::>::new(), |mut acc, (block_hash, txn_hash)| { - acc.entry(b256_to_h256(block_hash)) - .or_default() - .insert(b256_to_h256(txn_hash)); + acc.entry(block_hash).or_default().insert(txn_hash); acc }, ); @@ -2421,12 +2467,12 @@ async fn get_logs_and_transactions( // Associate each log with its receipt, when possible let mut log_triggers = Vec::new(); for log in logs.into_iter() { - let optional_receipt = log.transaction_hash.and_then(|txn| { - transaction_receipts_by_hash - .get(&b256_to_h256(txn)) - .cloned() - }); + let optional_receipt = log + .transaction_hash + .and_then(|txn| transaction_receipts_by_hash.get(&txn).cloned()); let web3_log = alloy_log_to_web3_log(log); + let optional_receipt = optional_receipt + .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)); let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(web3_log), optional_receipt)); log_triggers.push(value); } @@ -2437,13 +2483,14 @@ async fn get_logs_and_transactions( /// Tries to retrive all transaction receipts for a set of transaction hashes. async fn get_transaction_receipts_for_transaction_hashes( adapter: &EthereumAdapter, - transaction_hashes_by_block: &HashMap>, + transaction_hashes_by_block: &HashMap>, subgraph_metrics: Arc, logger: Logger, -) -> Result>, anyhow::Error> { +) -> Result>, anyhow::Error> { use std::collections::hash_map::Entry::Vacant; - let mut receipts_by_hash: HashMap> = HashMap::new(); + let mut receipts_by_hash: HashMap> = + HashMap::new(); // Return early if input set is empty if transaction_hashes_by_block.is_empty() { @@ -2452,17 +2499,17 @@ async fn get_transaction_receipts_for_transaction_hashes( // Keep a record of all unique transaction hashes for which we'll request receipts. We will // later use this to check if we have collected the receipts from all required transactions. - let mut unique_transaction_hashes: HashSet<&H256> = HashSet::new(); + let mut unique_transaction_hashes: HashSet<&B256> = HashSet::new(); // Request transaction receipts concurrently let receipt_futures = FuturesUnordered::new(); - let web3 = Arc::clone(&adapter.web3); + let alloy = Arc::clone(&adapter.alloy); for (block_hash, transaction_hashes) in transaction_hashes_by_block { for transaction_hash in transaction_hashes { unique_transaction_hashes.insert(transaction_hash); let receipt_future = fetch_transaction_receipt_with_retry( - web3.cheap_clone(), + alloy.cheap_clone(), *transaction_hash, *block_hash, logger.cheap_clone(), @@ -2524,11 +2571,12 @@ mod tests { EthereumBlockWithCalls, }; use graph::blockchain::BlockPtr; + use graph::prelude::alloy::primitives::B256; + use graph::prelude::alloy::providers::mock::Asserter; + use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; - use graph::prelude::web3::transports::test::TestTransport; use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Block, Bytes, H256}; - use graph::prelude::web3::Web3; use graph::prelude::EthereumCall; use jsonrpc_core::serde_json::{self, Value}; use std::collections::HashSet; @@ -2575,8 +2623,6 @@ mod tests { #[tokio::test] async fn test_check_block_receipts_support() { - let mut transport = TestTransport::default(); - let json_receipts = r#"[{ "blockHash": "0x23f785604642e91613881fc3c9d16740ee416e340fd36f3fa2239f203d68fd33", "blockNumber": "0x12f7f81", @@ -2598,22 +2644,21 @@ mod tests { // Helper function to run a single test case async fn run_test_case( - transport: &mut TestTransport, json_response: &str, expected_err: Option<&str>, supports_eip_1898: bool, call_only: bool, ) -> Result<(), anyhow::Error> { let json_value: Value = serde_json::from_str(json_response).unwrap(); - // let block_json: Value = serde_json::from_str(block).unwrap(); - transport.set_response(json_value); - // transport.set_response(block_json); - // transport.add_response(json_value); - let web3 = Arc::new(Web3::new(transport.clone())); + let asserter = Asserter::new(); + let provider = ProviderBuilder::new().connect_mocked_client(asserter.clone()); + + asserter.push_success(&json_value); + let result = check_block_receipt_support( - web3.clone(), - H256::zero(), + Arc::new(provider), + B256::ZERO, supports_eip_1898, call_only, ) @@ -2638,38 +2683,25 @@ mod tests { } // Test case 1: Valid block receipts - run_test_case(&mut transport, json_receipts, None, true, false) + run_test_case(json_receipts, None, true, false) .await .unwrap(); // Test case 2: Empty block receipts - run_test_case( - &mut transport, - json_empty, - Some("Block receipts are empty"), - true, - false, - ) - .await - .unwrap(); + run_test_case(json_empty, Some("Block receipts are empty"), true, false) + .await + .unwrap(); // Test case 3: Null response - run_test_case( - &mut transport, - "null", - Some("Block receipts are empty"), - true, - false, - ) - .await - .unwrap(); + run_test_case("null", Some("Block receipts are empty"), true, false) + .await + .unwrap(); // Test case 3: Simulating an RPC error // Note: In the context of this test, we cannot directly simulate an RPC error. // Instead, we simulate a response that would cause a decoding error, such as an unexpected key("error"). // The function should handle this as an error case. run_test_case( - &mut transport, r#"{"error":"RPC Error"}"#, Some("Error fetching block receipts:"), true, @@ -2680,7 +2712,6 @@ mod tests { // Test case 5: Does not support EIP-1898 run_test_case( - &mut transport, json_receipts, Some("Provider does not support EIP 1898"), false, @@ -2690,15 +2721,9 @@ mod tests { .unwrap(); // Test case 5: Does not support Call only adapters - run_test_case( - &mut transport, - json_receipts, - Some("Provider is call-only"), - true, - true, - ) - .await - .unwrap(); + run_test_case(json_receipts, Some("Provider is call-only"), true, true) + .await + .unwrap(); } #[test] diff --git a/graph/src/blockchain/mod.rs b/graph/src/blockchain/mod.rs index 00a9ac33e4e..0a0c7db2243 100644 --- a/graph/src/blockchain/mod.rs +++ b/graph/src/blockchain/mod.rs @@ -33,6 +33,7 @@ use crate::{ components::store::BlockNumber, prelude::{thiserror::Error, LinkResolver}, }; +use alloy::primitives::B256; use anyhow::{anyhow, Context, Error}; use async_trait::async_trait; use graph_derive::CheapClone; @@ -229,15 +230,15 @@ pub enum IngestorError { /// The Ethereum node does not know about this block for some reason, probably because it /// disappeared in a chain reorg. #[error("Receipt for tx {1:?} unavailable, block was likely uncled (block hash = {0:?})")] - ReceiptUnavailable(H256, H256), + ReceiptUnavailable(B256, B256), /// The Ethereum node does not know about this block for some reason #[error("Transaction receipts for block (block hash = {0:?}) is unavailable")] - BlockReceiptsUnavailable(H256), + BlockReceiptsUnavailable(B256), /// The Ethereum node does not know about this block for some reason #[error("Received confliciting block receipts for block (block hash = {0:?})")] - BlockReceiptsMismatched(H256), + BlockReceiptsMismatched(B256), /// An unexpected error occurred. #[error("Ingestor error: {0:#}")] diff --git a/graph/src/components/transaction_receipt.rs b/graph/src/components/transaction_receipt.rs index dc8eaf6a730..07c25694750 100644 --- a/graph/src/components/transaction_receipt.rs +++ b/graph/src/components/transaction_receipt.rs @@ -5,6 +5,11 @@ use web3::types::{TransactionReceipt, H256, U256, U64}; +use crate::{ + prelude::b256_to_h256, + util::conversions::{bool_to_web3_u64, u64_to_web3_u256, web3_u64_from_option}, +}; + /// Like web3::types::Receipt, but with fewer fields. #[derive(Debug, PartialEq, Eq)] pub struct LightTransactionReceipt { @@ -37,3 +42,16 @@ impl From for LightTransactionReceipt { } } } + +impl From for LightTransactionReceipt { + fn from(receipt: alloy::rpc::types::TransactionReceipt) -> Self { + LightTransactionReceipt { + transaction_hash: b256_to_h256(receipt.transaction_hash), + transaction_index: web3_u64_from_option(receipt.transaction_index), + block_hash: receipt.block_hash.map(b256_to_h256), + block_number: Some(web3_u64_from_option(receipt.block_number)), + gas_used: Some(u64_to_web3_u256(receipt.gas_used)), + status: Some(bool_to_web3_u64(receipt.status())), + } + } +} diff --git a/graph/src/lib.rs b/graph/src/lib.rs index fbaaed12d75..1a612cb93e7 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -177,8 +177,9 @@ pub mod prelude { pub use crate::log::split::split_logger; pub use crate::util::cache_weight::CacheWeight; pub use crate::util::conversions::{ - alloy_address_to_h160, alloy_address_to_web3_address, alloy_log_to_web3_log, b256_to_h256, - h160_to_alloy_address, h256_to_b256, web3_address_to_alloy_address, + alloy_address_to_h160, alloy_address_to_web3_address, alloy_log_to_web3_log, + alloy_transaction_receipt_to_web3_transaction_receipt, b256_to_h256, h160_to_alloy_address, + h256_to_b256, web3_address_to_alloy_address, }; pub use crate::util::futures::{retry, TimeoutError}; pub use crate::util::stats::MovingStats; diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index ae59032a0a9..3c1ed466102 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -20,6 +20,21 @@ pub fn b256_to_h256(b: B256) -> H256 { H256::from_slice(b.as_slice()) } +pub fn web3_u64_from_option(opt: Option) -> U64 { + U64::from(opt.unwrap_or(0)) +} + +pub fn u64_to_web3_u256(u: u64) -> U256 { + U256::from(u) +} + +pub fn bool_to_web3_u64(b: bool) -> U64 { + U64::from(if b { 1 } else { 0 }) +} + +pub fn u64_to_web3_u64(u: u64) -> U64 { + U64::from(u) +} /// Converts web3 H160 to alloy Address pub fn h160_to_alloy_address(h: H160) -> AlloyAddress { AlloyAddress::from_slice(h.as_bytes()) From db0033900d006f3f44abedd7bb65176a0e0ae1fa Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 18:36:06 +0530 Subject: [PATCH 27/44] chain/ethereum: Migrate load_blocks_rpc from futures01 to futures03 --- chain/ethereum/src/ethereum_adapter.rs | 56 ++++++++++++++++---------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 14831f6c13d..41410cf29cd 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -665,29 +665,42 @@ impl EthereumAdapter { &self, logger: Logger, ids: Vec, - ) -> impl Stream, Error = Error> + Send { + ) -> impl futures03::Stream, Error>> + Send { let web3 = self.web3.clone(); - stream::iter_ok::<_, Error>(ids.into_iter().map(move |hash| { + futures03::stream::iter(ids.into_iter().map(move |hash| { let web3 = web3.clone(); - retry(format!("load block {}", hash), &logger) - .redact_log_urls(true) - .limit(ENV_VARS.request_retries) - .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) - .run(move || { - Box::pin(web3.eth().block_with_txs(BlockId::Hash(hash))) - .compat() - .from_err::() - .and_then(move |block| { - block.map(Arc::new).ok_or_else(|| { - anyhow::anyhow!("Ethereum node did not find block {:?}", hash) - }) + let logger = logger.clone(); + + async move { + retry(format!("load block {}", hash), &logger) + .redact_log_urls(true) + .limit(ENV_VARS.request_retries) + .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) + .run(move || { + let web3 = web3.cheap_clone(); + async move { + web3.eth() + .block_with_txs(BlockId::Hash(hash)) + .await + .map_err(Error::from) + .and_then(|block| { + block.map(Arc::new).ok_or_else(|| { + anyhow::anyhow!( + "Ethereum node did not find block {:?}", + hash + ) + }) + }) + } + }) + .await + .map_err(|e| { + e.into_inner().unwrap_or_else(|| { + anyhow::anyhow!("Ethereum node took too long to return block {}", hash) }) - .compat() - }) - .boxed() - .compat() - .from_err() + }) + } })) .buffered(ENV_VARS.block_batch_size) } @@ -1587,10 +1600,9 @@ impl EthereumAdapterTrait for EthereumAdapter { // Return a stream that lazily loads batches of blocks. debug!(logger, "Requesting {} block(s)", missing_blocks.len()); - let new_blocks = self + let new_blocks: Vec> = self .load_blocks_rpc(logger.clone(), missing_blocks) - .collect() - .compat() + .try_collect() .await?; let upsert_blocks: Vec<_> = new_blocks .iter() From 82fb1f9fcf2abe3acf310205d2923b2b805d2fe6 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 24 Jun 2025 19:44:08 +0530 Subject: [PATCH 28/44] chain/ethereum: Refactor calls_in_block_range to eliminate Unpin errors and use futures03-ready closures --- chain/ethereum/src/ethereum_adapter.rs | 77 +++++++++++++------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 41410cf29cd..f66244b67fa 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -369,7 +369,7 @@ impl EthereumAdapter { from: BlockNumber, to: BlockNumber, addresses: Vec, - ) -> impl Stream + Send { + ) -> impl futures03::Stream> + Send { if from > to { panic!( "Can not produce a call stream on a backwards block range: from = {}, to = {}", @@ -385,34 +385,37 @@ impl EthereumAdapter { let eth = self; let logger = logger.clone(); - stream::unfold(from, move |start| { - if start > to { - return None; - } - let end = (start + step_size - 1).min(to); - let new_start = end + 1; - if start == end { - debug!(logger, "Requesting traces for block {}", start); - } else { - debug!(logger, "Requesting traces for blocks [{}, {}]", start, end); + + futures03::stream::try_unfold(from, move |start| { + let eth = eth.clone(); + let logger = logger.clone(); + let subgraph_metrics = subgraph_metrics.clone(); + let addresses = addresses.clone(); + + async move { + if start > to { + return Ok::, Error>(None); + } + + let end = (start + step_size - 1).min(to); + let new_start = end + 1; + + if start == end { + debug!(logger, "Requesting traces for block {}", start); + } else { + debug!(logger, "Requesting traces for blocks [{}, {}]", start, end); + } + + let traces = eth + .traces(logger, subgraph_metrics, start, end, addresses) + .await?; + Ok(Some(( + futures03::stream::iter(traces.into_iter().map(|t| Ok::<_, Error>(t))), + new_start, + ))) } - Some(graph::futures01::future::ok(( - eth.clone() - .traces( - logger.cheap_clone(), - subgraph_metrics.clone(), - start, - end, - addresses.clone(), - ) - .boxed() - .compat(), - new_start, - ))) }) - .buffered(ENV_VARS.block_batch_size) - .map(stream::iter_ok) - .flatten() + .try_flatten() } fn log_stream( @@ -899,14 +902,13 @@ impl EthereumAdapter { Box::new( eth.trace_stream(logger, subgraph_metrics, from, to, addresses) - .filter_map(|trace| EthereumCall::try_from_trace(&trace)) - .filter(move |call| { - // `trace_filter` can only filter by calls `to` an address and - // a block range. Since subgraphs are subscribing to calls - // for a specific contract function an additional filter needs - // to be applied - call_filter.matches(call) - }), + .try_filter_map(move |trace| { + let maybe_call = EthereumCall::try_from_trace(&trace) + .filter(|call| call_filter.matches(call)); + futures03::future::ready(Ok(maybe_call)) + }) + .boxed() + .compat(), ) } @@ -989,7 +991,7 @@ impl EthereumAdapter { ) -> Result, Error> { let eth = self.clone(); let addresses = Vec::new(); - let traces = eth + let traces: Vec = eth .trace_stream( logger, subgraph_metrics.clone(), @@ -997,8 +999,7 @@ impl EthereumAdapter { block_number, addresses, ) - .collect() - .compat() + .try_collect() .await?; // `trace_stream` returns all of the traces for the block, and this From dbf24ceb806b5995d883269f96ce44827c079406 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 25 Jun 2025 18:18:37 +0530 Subject: [PATCH 29/44] more conversions --- graph/src/util/conversions.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 3c1ed466102..eaa01948188 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use web3::types::Bytes; + use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; use crate::prelude::alloy::rpc::types::{ Block as AlloyBlock, Log as AlloyLog, TransactionReceipt as AlloyTransactionReceipt, @@ -55,6 +57,20 @@ pub fn alloy_address_to_web3_address(addr: AlloyAddress) -> Web3Address { alloy_address_to_h160(addr) } +// u256 to web3 U256 +pub fn alloy_u256_to_web3_u256(_u: alloy::primitives::U256) -> U256 { + unimplemented!(); +} + +pub fn alloy_bytes_to_web3_bytes(_b: alloy::primitives::Bytes) -> Bytes { + unimplemented!(); +} + +// u256 to alloy U256 +pub fn web3_u256_to_alloy_u256(u: U256) -> U256 { + U256::from(u) +} + /// Converts alloy Log to web3 Log pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { Web3Log { From 2465e9234160223410c9dafe1aee9f5a779408f3 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 25 Jun 2025 18:19:15 +0530 Subject: [PATCH 30/44] chain/ethereum: migrate traces to use alloy --- chain/ethereum/src/ethereum_adapter.rs | 219 ++++++++++++++++--------- graph/src/components/ethereum/types.rs | 40 ++--- 2 files changed, 158 insertions(+), 101 deletions(-) diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index f66244b67fa..a08140af73c 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -19,15 +19,27 @@ use graph::futures03::future::try_join_all; use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; -use graph::prelude::alloy; -use graph::prelude::alloy::primitives::B256; -use graph::prelude::alloy::rpc::types::{TransactionInput, TransactionRequest}; -use graph::prelude::alloy::transports::RpcError; - -use graph::prelude::alloy_transaction_receipt_to_web3_transaction_receipt; -use graph::prelude::h256_to_b256; -use graph::prelude::tokio::try_join; -use graph::prelude::{alloy_log_to_web3_log, b256_to_h256}; +use graph::prelude::{ + alloy::{ + self, + primitives::B256, + providers::{ + ext::TraceApi, + fillers::{ + BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, + }, + Identity, Provider, RootProvider, + }, + rpc::types::{ + trace::{filter::TraceFilter as AlloyTraceFilter, parity::LocalizedTransactionTrace}, + TransactionInput, TransactionRequest, + }, + transports::{RpcError, TransportErrorKind}, + }, + alloy_log_to_web3_log, alloy_transaction_receipt_to_web3_transaction_receipt, b256_to_h256, + h160_to_alloy_address, h256_to_b256, + tokio::try_join, +}; use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; @@ -41,11 +53,7 @@ use graph::{ TimeoutError, }, }; -use graph::{ - components::ethereum::*, - prelude::web3::api::Web3, - prelude::web3::types::{Trace, TraceFilter, TraceFilterBuilder, H160}, -}; +use graph::{components::ethereum::*, prelude::web3::api::Web3, prelude::web3::types::H160}; use itertools::Itertools; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::convert::TryFrom; @@ -73,12 +81,20 @@ use crate::{ ENV_VARS, }; +type AlloyProvider = FillProvider< + JoinFill< + Identity, + JoinFill>>, + >, + RootProvider, +>; + #[derive(Clone)] pub struct EthereumAdapter { logger: Logger, provider: String, web3: Arc>, - alloy: Arc, + alloy: Arc, metrics: Arc, supports_eip_1898: bool, call_only: bool, @@ -164,79 +180,26 @@ impl EthereumAdapter { subgraph_metrics: Arc, from: BlockNumber, to: BlockNumber, - addresses: Vec, - ) -> Result, Error> { + addresses: Vec, + ) -> Result, Error> { assert!(!self.call_only); - let eth = self.clone(); let retry_log_message = format!("trace_filter RPC call for block range: [{}..{}]", from, to); + let eth = self.clone(); + retry(retry_log_message, &logger) .redact_log_urls(true) .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let trace_filter: TraceFilter = match addresses.len() { - 0 => TraceFilterBuilder::default() - .from_block(from.into()) - .to_block(to.into()) - .build(), - _ => TraceFilterBuilder::default() - .from_block(from.into()) - .to_block(to.into()) - .to_address(addresses.clone()) - .build(), - }; - - let eth = eth.cheap_clone(); - let logger_for_triggers = logger.clone(); - let logger_for_error = logger.clone(); - let start = Instant::now(); + let eth = eth.clone(); + let logger = logger.clone(); let subgraph_metrics = subgraph_metrics.clone(); - let provider_metrics = eth.metrics.clone(); - let provider = self.provider.clone(); - + let addresses = addresses.clone(); async move { - let result = eth - .web3 - .trace() - .filter(trace_filter) + eth.execute_trace_filter_request(logger, subgraph_metrics, from, to, addresses) .await - .map(move |traces| { - if !traces.is_empty() { - if to == from { - debug!( - logger_for_triggers, - "Received {} traces for block {}", - traces.len(), - to - ); - } else { - debug!( - logger_for_triggers, - "Received {} traces for blocks [{}, {}]", - traces.len(), - from, - to - ); - } - } - traces - }) - .map_err(Error::from); - - let elapsed = start.elapsed().as_secs_f64(); - provider_metrics.observe_request(elapsed, "trace_filter", &provider); - subgraph_metrics.observe_request(elapsed, "trace_filter", &provider); - if let Err(e) = &result { - provider_metrics.add_error("trace_filter", &provider); - subgraph_metrics.add_error("trace_filter", &provider); - debug!( - logger_for_error, - "Error querying traces error = {:#} from = {} to = {}", e, from, to - ); - } - result } }) .map_err(move |e| { @@ -252,6 +215,93 @@ impl EthereumAdapter { .await } + async fn execute_trace_filter_request( + &self, + logger: Logger, + subgraph_metrics: Arc, + from: BlockNumber, + to: BlockNumber, + addresses: Vec, + ) -> Result, Error> { + let alloy_trace_filter = Self::build_trace_filter(from, to, &addresses); + let start = Instant::now(); + + let result = self.alloy.trace_filter(&alloy_trace_filter).await; + + if let Ok(traces) = &result { + self.log_trace_results(&logger, from, to, traces.len()); + } + + self.record_trace_metrics( + &subgraph_metrics, + start.elapsed().as_secs_f64(), + &result, + from, + to, + &logger, + ); + + result.map_err(Error::from) + } + + fn build_trace_filter( + from: BlockNumber, + to: BlockNumber, + addresses: &[alloy::primitives::Address], + ) -> AlloyTraceFilter { + let filter = AlloyTraceFilter::default() + .from_block(from as u64) + .to_block(to as u64); + + if !addresses.is_empty() { + filter.to_address(addresses.to_vec()) + } else { + filter + } + } + + fn log_trace_results( + &self, + logger: &Logger, + from: BlockNumber, + to: BlockNumber, + trace_len: usize, + ) { + if trace_len > 0 { + if to == from { + debug!(logger, "Received {} traces for block {}", trace_len, to); + } else { + debug!( + logger, + "Received {} traces for blocks [{}, {}]", trace_len, from, to + ); + } + } + } + + fn record_trace_metrics( + &self, + subgraph_metrics: &Arc, + elapsed: f64, + result: &Result, RpcError>, + from: BlockNumber, + to: BlockNumber, + logger: &Logger, + ) { + self.metrics + .observe_request(elapsed, "trace_filter", &self.provider); + subgraph_metrics.observe_request(elapsed, "trace_filter", &self.provider); + + if let Err(e) = result { + self.metrics.add_error("trace_filter", &self.provider); + subgraph_metrics.add_error("trace_filter", &self.provider); + debug!( + logger, + "Error querying traces error = {:#} from = {} to = {}", e, from, to + ); + } + } + // This is a lazy check for block receipt support. It is only called once and then the result is // cached. The result is not used for anything critical, so it is fine to be lazy. async fn check_block_receipt_support_and_update_cache( @@ -368,8 +418,8 @@ impl EthereumAdapter { subgraph_metrics: Arc, from: BlockNumber, to: BlockNumber, - addresses: Vec, - ) -> impl futures03::Stream> + Send { + addresses: Vec, + ) -> impl futures03::Stream> + Send { if from > to { panic!( "Can not produce a call stream on a backwards block range: from = {}, to = {}", @@ -900,6 +950,11 @@ impl EthereumAdapter { addresses = vec![]; } + let addresses = addresses + .iter() + .map(|addr| h160_to_alloy_address(*addr)) + .collect(); + Box::new( eth.trace_stream(logger, subgraph_metrics, from, to, addresses) .try_filter_map(move |trace| { @@ -987,11 +1042,11 @@ impl EthereumAdapter { logger: &Logger, subgraph_metrics: Arc, block_number: BlockNumber, - block_hash: H256, + block_hash: alloy::primitives::B256, ) -> Result, Error> { let eth = self.clone(); let addresses = Vec::new(); - let traces: Vec = eth + let traces: Vec = eth .trace_stream( logger, subgraph_metrics.clone(), @@ -1017,7 +1072,7 @@ impl EthereumAdapter { // all the traces for the block, we need to ensure that the // block hash for the traces is equal to the desired block hash. // Assume all traces are for the same block. - if traces.iter().nth(0).unwrap().block_hash != block_hash { + if traces.iter().nth(0).unwrap().block_hash != Some(block_hash) { return Err(anyhow!( "Trace stream returned traces for an unexpected block: \ number = `{}`, hash = `{}`", @@ -1835,7 +1890,7 @@ pub(crate) async fn get_calls( subgraph_metrics.clone(), BlockNumber::try_from(ethereum_block.block.number.unwrap().as_u64()) .unwrap(), - ethereum_block.block.hash.unwrap(), + h256_to_b256(ethereum_block.block.hash.unwrap()), ) .await? }; diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index b43730590d4..25a484ba41f 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -1,13 +1,12 @@ +use alloy::rpc::types::trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}; use serde::{Deserialize, Serialize}; use std::{convert::TryFrom, sync::Arc}; -use web3::types::{ - Action, Address, Block, Bytes, Log, Res, Trace, Transaction, TransactionReceipt, H256, U256, - U64, -}; +use web3::types::{Address, Block, Bytes, Log, Transaction, TransactionReceipt, H256, U256, U64}; use crate::{ blockchain::{BlockPtr, BlockTime}, - prelude::BlockNumber, + prelude::{alloy_address_to_h160, b256_to_h256, BlockNumber}, + util::conversions::{alloy_bytes_to_web3_bytes, alloy_u256_to_web3_u256, u64_to_web3_u256}, }; pub type LightEthereumBlock = Block; @@ -125,21 +124,24 @@ pub struct EthereumCall { } impl EthereumCall { - pub fn try_from_trace(trace: &Trace) -> Option { + pub fn try_from_trace(trace: &LocalizedTransactionTrace) -> Option { // The parity-ethereum tracing api returns traces for operations which had execution errors. // Filter errorful traces out, since call handlers should only run on successful CALLs. - if trace.error.is_some() { + + let tx_trace = &trace.trace; + + if tx_trace.error.is_some() { return None; } // We are only interested in traces from CALLs - let call = match &trace.action { + let call = match &tx_trace.action { // Contract to contract value transfers compile to the CALL opcode // and have no input. Call handlers are for triggering on explicit method calls right now. Action::Call(call) if call.input.0.len() >= 4 => call, _ => return None, }; - let (output, gas_used) = match &trace.result { - Some(Res::Call(result)) => (result.output.clone(), result.gas_used), + let (output, gas_used) = match &tx_trace.result { + Some(TraceOutput::Call(result)) => (result.output.clone(), result.gas_used), _ => return None, }; @@ -148,15 +150,15 @@ impl EthereumCall { let transaction_index = trace.transaction_position? as u64; Some(EthereumCall { - from: call.from, - to: call.to, - value: call.value, - gas_used, - input: call.input.clone(), - output, - block_number: trace.block_number as BlockNumber, - block_hash: trace.block_hash, - transaction_hash: trace.transaction_hash, + from: alloy_address_to_h160(call.from), + to: alloy_address_to_h160(call.to), + value: alloy_u256_to_web3_u256(call.value), + gas_used: u64_to_web3_u256(gas_used), + input: alloy_bytes_to_web3_bytes(call.input.clone()), + output: alloy_bytes_to_web3_bytes(output), + block_number: trace.block_number? as BlockNumber, + block_hash: trace.block_hash.map(|h| b256_to_h256(h))?, + transaction_hash: trace.transaction_hash.map(|h| b256_to_h256(h)), transaction_index, }) } From d8b1e102a73d5080f8326eead527a62b8cc638b0 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 25 Jun 2025 19:04:22 +0530 Subject: [PATCH 31/44] more conversions --- graph/src/util/conversions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index eaa01948188..9bd9471b2a2 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -95,7 +95,7 @@ pub fn alloy_transaction_receipt_to_web3_transaction_receipt( } /// Converts alloy Block to web3 Block -pub fn alloy_block_to_web3_block(_block: AlloyBlock) -> Web3Block { +pub fn alloy_block_to_web3_block(_block: Arc) -> Arc> { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) From f79cffbed8744d7ce411040aa314cf059036ac2b Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 25 Jun 2025 19:04:40 +0530 Subject: [PATCH 32/44] chain/ethereum: migrate block methods to alloy part 1 --- chain/ethereum/src/adapter.rs | 16 ++--- chain/ethereum/src/ethereum_adapter.rs | 84 +++++++++-------------- chain/ethereum/src/ingestor.rs | 9 +-- graph/src/blockchain/mod.rs | 3 +- graph/src/blockchain/types.rs | 2 +- graph/src/util/conversions.rs | 8 ++- node/src/manager/commands/chain.rs | 14 ++-- node/src/manager/commands/check_blocks.rs | 10 ++- 8 files changed, 69 insertions(+), 77 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 7cc01286a60..38e7050a673 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -7,6 +7,8 @@ use graph::data_source::common::ContractCall; use graph::firehose::CallToFilter; use graph::firehose::CombinedFilter; use graph::firehose::LogFilter; +use graph::prelude::alloy::primitives::B256; +use graph::prelude::alloy::rpc::types::Block as AlloyBlock; use graph::prelude::alloy::transports::{RpcError, TransportErrorKind}; use graph::prelude::web3::types::H160; use itertools::Itertools; @@ -1244,12 +1246,6 @@ pub trait EthereumAdapter: Send + Sync + 'static { /// Get the latest block, with only the header and transaction hashes. async fn latest_block_ptr(&self, logger: &Logger) -> Result; - async fn load_block( - &self, - logger: &Logger, - block_hash: H256, - ) -> Result; - /// Load Ethereum blocks in bulk, returning results as they come back as a Stream. /// May use the `chain_store` as a cache. async fn load_blocks( @@ -1263,20 +1259,20 @@ pub trait EthereumAdapter: Send + Sync + 'static { async fn block_by_hash( &self, logger: &Logger, - block_hash: H256, - ) -> Result, Error>; + block_hash: B256, + ) -> Result, Error>; async fn block_by_number( &self, logger: &Logger, block_number: BlockNumber, - ) -> Result, Error>; + ) -> Result, Error>; /// Load full information for the specified `block` (in particular, transaction receipts). async fn load_full_block( &self, logger: &Logger, - block: LightEthereumBlock, + block: AlloyBlock, ) -> Result; /// Finds the hash and number of the lowest non-null block with height greater than or equal to diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index a08140af73c..b08364a8229 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -32,17 +32,18 @@ use graph::prelude::{ }, rpc::types::{ trace::{filter::TraceFilter as AlloyTraceFilter, parity::LocalizedTransactionTrace}, - TransactionInput, TransactionRequest, + Block as AlloyBlock, TransactionInput, TransactionRequest, }, transports::{RpcError, TransportErrorKind}, }, - alloy_log_to_web3_log, alloy_transaction_receipt_to_web3_transaction_receipt, b256_to_h256, + alloy_log_to_web3_log, alloy_transaction_receipt_to_web3_transaction_receipt, h160_to_alloy_address, h256_to_b256, tokio::try_join, }; use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; +use graph::util::conversions::alloy_block_to_web3_block; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ @@ -1258,27 +1259,12 @@ impl EthereumAdapterTrait for EthereumAdapter { .await } - async fn load_block( - &self, - logger: &Logger, - block_hash: H256, - ) -> Result { - self.block_by_hash(logger, block_hash) - .await? - .ok_or_else(move || { - anyhow!( - "Ethereum node could not find block with hash {}", - block_hash - ) - }) - } - async fn block_by_hash( &self, logger: &Logger, - block_hash: H256, - ) -> Result, Error> { - let web3 = self.web3.clone(); + block_hash: B256, + ) -> Result, Error> { + let alloy = self.alloy.clone(); let logger = logger.clone(); let retry_log_message = format!( "eth_getBlockByHash RPC call for block hash {:?}", @@ -1290,10 +1276,11 @@ impl EthereumAdapterTrait for EthereumAdapter { .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - web3.eth() - .block_with_txs(BlockId::Hash(block_hash)) + alloy + .get_block_by_hash(block_hash) + .full() .await .map_err(Error::from) } @@ -1310,8 +1297,8 @@ impl EthereumAdapterTrait for EthereumAdapter { &self, logger: &Logger, block_number: BlockNumber, - ) -> Result, Error> { - let web3 = self.web3.clone(); + ) -> Result, Error> { + let alloy = self.alloy.clone(); let logger = logger.clone(); let retry_log_message = format!( "eth_getBlockByNumber RPC call for block number {}", @@ -1322,10 +1309,13 @@ impl EthereumAdapterTrait for EthereumAdapter { .no_limit() .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.clone(); async move { - web3.eth() - .block_with_txs(BlockId::Number(block_number.into())) + alloy + .get_block_by_number(alloy::rpc::types::BlockNumberOrTag::Number( + block_number as u64, + )) + .full() .await .map_err(Error::from) } @@ -1344,50 +1334,42 @@ impl EthereumAdapterTrait for EthereumAdapter { async fn load_full_block( &self, logger: &Logger, - block: LightEthereumBlock, + block: AlloyBlock, ) -> Result { let alloy = self.alloy.clone(); let logger = logger.clone(); - let block_hash = block.hash.expect("block is missing block hash"); + let block_hash = block.header.hash; // The early return is necessary for correctness, otherwise we'll // request an empty batch which is not valid in JSON-RPC. if block.transactions.is_empty() { trace!(logger, "Block {} contains no transactions", block_hash); return Ok(EthereumBlock { - block: Arc::new(block), + block: Arc::new(alloy_block_to_web3_block(block)), transaction_receipts: Vec::new(), }); } - let hashes: Vec<_> = block.transactions.iter().map(|txn| txn.hash).collect(); + let hashes: Vec<_> = block.transactions.hashes().collect(); let supports_block_receipts = self .check_block_receipt_support_and_update_cache( alloy.clone(), - h256_to_b256(block_hash), + block_hash, self.supports_eip_1898, self.call_only, logger.clone(), ) .await; - let hashes_b256 = hashes.iter().map(|hash| h256_to_b256(*hash)).collect(); - let block_hash_b256 = h256_to_b256(block_hash); - fetch_receipts_with_retry( - alloy, - hashes_b256, - block_hash_b256, - logger, - supports_block_receipts, - ) - .await - .map(|transaction_receipts| EthereumBlock { - block: Arc::new(block), - transaction_receipts: transaction_receipts - .into_iter() - .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)) - .collect(), - }) + fetch_receipts_with_retry(alloy, hashes, block_hash, logger, supports_block_receipts) + .await + .map(|transaction_receipts| EthereumBlock { + block: Arc::new(alloy_block_to_web3_block(block)), + transaction_receipts: transaction_receipts + .into_iter() + .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)) + .collect(), + }) } async fn get_balance( @@ -2447,7 +2429,7 @@ fn resolve_transaction_receipt( // considers this block to be in the main chain. Nothing we can do from here except // give up trying to ingest this block. There is no way to get the transaction // receipt from this block. - Err(IngestorError::BlockUnavailable(b256_to_h256(block_hash))) + Err(IngestorError::BlockUnavailable(block_hash)) } else { Ok(receipt) } diff --git a/chain/ethereum/src/ingestor.rs b/chain/ethereum/src/ingestor.rs index 92293510fae..0367b9d6281 100644 --- a/chain/ethereum/src/ingestor.rs +++ b/chain/ethereum/src/ingestor.rs @@ -3,14 +3,15 @@ use crate::{EthereumAdapter, EthereumAdapterTrait as _}; use graph::blockchain::client::ChainClient; use graph::blockchain::BlockchainKind; use graph::components::network_provider::ChainName; +use graph::prelude::alloy::primitives::B256; use graph::slog::o; use graph::util::backoff::ExponentialBackoff; use graph::{ blockchain::{BlockHash, BlockIngestor, BlockPtr, IngestorError}, cheap_clone::CheapClone, prelude::{ - async_trait, error, info, tokio, trace, warn, web3::types::H256, ChainStore, Error, - EthereumBlockWithCalls, LogCode, Logger, + async_trait, error, info, tokio, trace, warn, ChainStore, Error, EthereumBlockWithCalls, + LogCode, Logger, }, }; use std::{sync::Arc, time::Duration}; @@ -168,8 +169,8 @@ impl PollingBlockIngestor { eth_adapter: &Arc, block_hash: &BlockHash, ) -> Result, IngestorError> { - // TODO: H256::from_slice can panic - let block_hash = H256::from_slice(block_hash.as_slice()); + // TODO: B256::from_slice can panic + let block_hash = B256::from_slice(block_hash.as_slice()); // Get the fully populated block let block = eth_adapter diff --git a/graph/src/blockchain/mod.rs b/graph/src/blockchain/mod.rs index 0a0c7db2243..cb8733f3453 100644 --- a/graph/src/blockchain/mod.rs +++ b/graph/src/blockchain/mod.rs @@ -47,7 +47,6 @@ use std::{ str::FromStr, sync::Arc, }; -use web3::types::H256; pub use block_stream::{ChainHeadUpdateListener, ChainHeadUpdateStream, TriggersAdapter}; pub use builder::{BasicBlockchainBuilder, BlockchainBuilder}; @@ -225,7 +224,7 @@ pub enum IngestorError { /// The Ethereum node does not know about this block for some reason, probably because it /// disappeared in a chain reorg. #[error("Block data unavailable, block was likely uncled (block hash = {0:?})")] - BlockUnavailable(H256), + BlockUnavailable(B256), /// The Ethereum node does not know about this block for some reason, probably because it /// disappeared in a chain reorg. diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index eb147e8baf7..f12e3979373 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -97,7 +97,7 @@ impl From> for BlockHash { impl From for BlockHash { fn from(hash: alloy::primitives::B256) -> Self { - BlockHash(hash.0.to_vec().into()) + BlockHash(hash.as_slice().into()) } } diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 9bd9471b2a2..6763552da7a 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -95,7 +95,13 @@ pub fn alloy_transaction_receipt_to_web3_transaction_receipt( } /// Converts alloy Block to web3 Block -pub fn alloy_block_to_web3_block(_block: Arc) -> Arc> { +pub fn alloy_block_to_web3_block_arc(_block: Arc) -> Arc> { + unimplemented!( + "Block conversion from alloy to web3 not yet implemented - will be done when needed" + ) +} + +pub fn alloy_block_to_web3_block(_block: AlloyBlock) -> Web3Block { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) diff --git a/node/src/manager/commands/chain.rs b/node/src/manager/commands/chain.rs index 905568a5637..595d77b7eab 100644 --- a/node/src/manager/commands/chain.rs +++ b/node/src/manager/commands/chain.rs @@ -12,9 +12,9 @@ use graph::components::store::ChainIdStore; use graph::components::store::StoreError; use graph::prelude::BlockNumber; use graph::prelude::ChainStore as _; -use graph::prelude::LightEthereumBlockExt; use graph::prelude::{anyhow, anyhow::bail}; use graph::slog::Logger; +use graph::util::conversions::alloy_block_to_web3_block; use graph::{ components::store::BlockStore as _, components::store::ChainHeadStore as _, prelude::anyhow::Error, @@ -276,14 +276,18 @@ pub async fn ingest( else { bail!("block number {number} not found"); }; - let ptr = block.block_ptr(); + let hash = block.header.hash; + let number = block.header.number; // For inserting the block, it doesn't matter whether the block is final or not. - let block = Arc::new(BlockFinality::Final(Arc::new(block))); + let block = Arc::new(BlockFinality::Final(Arc::new(alloy_block_to_web3_block( + block, + )))); chain_store.upsert_block(block).await?; - let rows = chain_store.confirm_block_hash(ptr.number, &ptr.hash)?; + let hash = hash.into(); + let rows = chain_store.confirm_block_hash(number as i32, &hash)?; - println!("Inserted block {}", ptr); + println!("Inserted block {}", hash); if rows > 0 { println!(" (also deleted {rows} duplicate row(s) with that number)"); } diff --git a/node/src/manager/commands/check_blocks.rs b/node/src/manager/commands/check_blocks.rs index 0afa54bd7d3..793a1677c3d 100644 --- a/node/src/manager/commands/check_blocks.rs +++ b/node/src/manager/commands/check_blocks.rs @@ -155,7 +155,10 @@ mod steps { use graph::{ anyhow::bail, - prelude::serde_json::{self, Value}, + prelude::{ + h256_to_b256, + serde_json::{self, Value}, + }, }; use json_structural_diff::{colorize as diff_to_string, JsonDiff}; @@ -201,13 +204,14 @@ mod steps { ethereum_adapter: &EthereumAdapter, logger: &Logger, ) -> anyhow::Result { + let block_hash = h256_to_b256(*block_hash); let provider_block = ethereum_adapter - .block_by_hash(logger, *block_hash) + .block_by_hash(logger, block_hash) .await .with_context(|| format!("failed to fetch block {block_hash}"))? .ok_or_else(|| anyhow!("JRPC provider found no block with hash {block_hash:?}"))?; ensure!( - provider_block.hash == Some(*block_hash), + provider_block.header.hash == block_hash, "Provider responded with a different block hash" ); serde_json::to_value(provider_block) From 85cf80d676de7a96292a83896e55f830c27635ab Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 25 Jun 2025 19:36:20 +0530 Subject: [PATCH 33/44] chain/ethereum: migrate block methods to alloy part 2 --- chain/ethereum/src/adapter.rs | 4 +-- chain/ethereum/src/chain.rs | 2 +- chain/ethereum/src/ethereum_adapter.rs | 47 ++++++++++++++------------ graph/src/blockchain/types.rs | 9 +++-- graph/src/components/ethereum/types.rs | 42 ++++++++++++++++++++++- graph/src/util/conversions.rs | 7 ++++ 6 files changed, 84 insertions(+), 27 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 38e7050a673..ccb787da60d 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1252,8 +1252,8 @@ pub trait EthereumAdapter: Send + Sync + 'static { &self, logger: Logger, chain_store: Arc, - block_hashes: HashSet, - ) -> Result>, Error>; + block_hashes: HashSet, + ) -> Result>, Error>; /// Find a block by its hash. async fn block_by_hash( diff --git a/chain/ethereum/src/chain.rs b/chain/ethereum/src/chain.rs index 35c155b9c0f..bcb2948ab01 100644 --- a/chain/ethereum/src/chain.rs +++ b/chain/ethereum/src/chain.rs @@ -1108,7 +1108,7 @@ impl TriggersAdapterTrait for TriggersAdapter { .load_blocks( self.logger.cheap_clone(), self.chain_store.cheap_clone(), - HashSet::from_iter(Some(block.hash_as_h256())), + HashSet::from_iter(Some(block.hash_as_b256())), ) .await?; assert_eq!(blocks.len(), 1); diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index b08364a8229..fc039abbbef 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -19,6 +19,7 @@ use graph::futures03::future::try_join_all; use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; +use graph::prelude::alloy::consensus::BlockHeader; use graph::prelude::{ alloy::{ self, @@ -44,12 +45,13 @@ use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; use graph::util::conversions::alloy_block_to_web3_block; +use graph::util::conversions::alloy_block_to_web3_block_arc; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ anyhow::{self, anyhow, bail, ensure, Context}, async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, - web3::types::{BlockId, Transaction, H256}, + web3::types::{Transaction, H256}, BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, TimeoutError, }, @@ -718,12 +720,12 @@ impl EthereumAdapter { fn load_blocks_rpc( &self, logger: Logger, - ids: Vec, - ) -> impl futures03::Stream, Error>> + Send { - let web3 = self.web3.clone(); + ids: Vec, + ) -> impl futures03::Stream, Error>> + Send { + let alloy = self.alloy.clone(); futures03::stream::iter(ids.into_iter().map(move |hash| { - let web3 = web3.clone(); + let alloy = alloy.clone(); let logger = logger.clone(); async move { @@ -732,10 +734,11 @@ impl EthereumAdapter { .limit(ENV_VARS.request_retries) .timeout_secs(ENV_VARS.json_rpc_timeout.as_secs()) .run(move || { - let web3 = web3.cheap_clone(); + let alloy = alloy.cheap_clone(); async move { - web3.eth() - .block_with_txs(BlockId::Hash(hash)) + alloy + .get_block_by_hash(hash) + .full() .await .map_err(Error::from) .and_then(|block| { @@ -1615,11 +1618,11 @@ impl EthereumAdapterTrait for EthereumAdapter { &self, logger: Logger, chain_store: Arc, - block_hashes: HashSet, - ) -> Result>, Error> { + block_hashes: HashSet, + ) -> Result>, Error> { let block_hashes: Vec<_> = block_hashes.iter().cloned().collect(); // Search for the block in the store first then use json-rpc as a backup. - let mut blocks: Vec> = chain_store + let mut blocks: Vec> = chain_store .cheap_clone() .blocks(block_hashes.iter().map(|&b| b.into()).collect::>()) .await @@ -1633,18 +1636,18 @@ impl EthereumAdapterTrait for EthereumAdapter { let missing_blocks = Vec::from_iter( block_hashes .into_iter() - .filter(|hash| !blocks.iter().any(|b| b.hash == Some(*hash))), + .filter(|hash| !blocks.iter().any(|b| b.header.hash == *hash)), ); // Return a stream that lazily loads batches of blocks. debug!(logger, "Requesting {} block(s)", missing_blocks.len()); - let new_blocks: Vec> = self + let new_blocks: Vec> = self .load_blocks_rpc(logger.clone(), missing_blocks) .try_collect() .await?; let upsert_blocks: Vec<_> = new_blocks .iter() - .map(|block| BlockFinality::Final(block.clone())) + .map(|block| BlockFinality::Final(alloy_block_to_web3_block_arc(block.clone()))) .collect(); let block_refs: Vec<_> = upsert_blocks .iter() @@ -1654,7 +1657,7 @@ impl EthereumAdapterTrait for EthereumAdapter { error!(logger, "Error writing to block cache {}", e); } blocks.extend(new_blocks); - blocks.sort_by_key(|block| block.number); + blocks.sort_by_key(|block| block.header.number); Ok(blocks) } } @@ -1697,7 +1700,7 @@ pub(crate) async fn blocks_with_triggers( debug!(logger, "Finding nearest valid `to` block to {}", to); let to_ptr = eth.next_existing_ptr_to_number(&logger, to).await?; - let to_hash = to_ptr.hash_as_h256(); + let to_hash = to_ptr.hash_as_b256(); let to = to_ptr.block_number(); // This is for `start` triggers which can be initialization handlers which needs to be run @@ -1774,8 +1777,10 @@ pub(crate) async fn blocks_with_triggers( .await .with_context(|| format!("Failed to obtain triggers for block {}", to))?; - let mut block_hashes: HashSet = - triggers.iter().map(EthereumTrigger::block_hash).collect(); + let mut block_hashes: HashSet = triggers + .iter() + .map(|trigger| h256_to_b256(trigger.block_hash())) + .collect(); let mut triggers_by_block: HashMap> = triggers.into_iter().fold(HashMap::new(), |mut map, t| { map.entry(t.block_number()).or_default().push(t); @@ -1795,15 +1800,15 @@ pub(crate) async fn blocks_with_triggers( .await? .into_iter() .map( - move |block| match triggers_by_block.remove(&(block.number() as BlockNumber)) { + move |block| match triggers_by_block.remove(&(block.header.number() as BlockNumber)) { Some(triggers) => Ok(BlockWithTriggers::new( - BlockFinality::Final(block), + BlockFinality::Final(alloy_block_to_web3_block_arc(block)), triggers, &logger2, )), None => Err(anyhow!( "block {} not found in `triggers_by_block`", - block.block_ptr() + BlockPtr::new(block.header.hash.into(), block.header.number as i32) )), }, ) diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index f12e3979373..2e1c31add2d 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -1,3 +1,4 @@ +use alloy::primitives::B256; use anyhow::anyhow; use diesel::deserialize::FromSql; use diesel::pg::Pg; @@ -95,8 +96,8 @@ impl From> for BlockHash { } } -impl From for BlockHash { - fn from(hash: alloy::primitives::B256) -> Self { +impl From for BlockHash { + fn from(hash: B256) -> Self { BlockHash(hash.as_slice().into()) } } @@ -183,6 +184,10 @@ impl BlockPtr { H256::from_slice(&self.hash_slice()[..32]) } + pub fn hash_as_b256(&self) -> B256 { + B256::from_slice(&self.hash_slice()[..32]) + } + pub fn hash_slice(&self) -> &[u8] { self.hash.0.as_ref() } diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index 25a484ba41f..bd4d3d96756 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -4,12 +4,16 @@ use std::{convert::TryFrom, sync::Arc}; use web3::types::{Address, Block, Bytes, Log, Transaction, TransactionReceipt, H256, U256, U64}; use crate::{ + alloy_todo, blockchain::{BlockPtr, BlockTime}, - prelude::{alloy_address_to_h160, b256_to_h256, BlockNumber}, + prelude::{ + alloy::rpc::types::Block as AlloyBlock, alloy_address_to_h160, b256_to_h256, BlockNumber, + }, util::conversions::{alloy_bytes_to_web3_bytes, alloy_u256_to_web3_u256, u64_to_web3_u256}, }; pub type LightEthereumBlock = Block; +pub type LightEthereumBlockAlloy = AlloyBlock; pub trait LightEthereumBlockExt { fn number(&self) -> BlockNumber; @@ -21,6 +25,42 @@ pub trait LightEthereumBlockExt { fn timestamp(&self) -> BlockTime; } +impl LightEthereumBlockExt for LightEthereumBlockAlloy { + fn number(&self) -> BlockNumber { + alloy_todo!() + } + + fn timestamp(&self) -> BlockTime { + alloy_todo!() + } + + fn transaction_for_log(&self, _log: &Log) -> Option { + alloy_todo!() + } + + fn transaction_for_call(&self, _call: &EthereumCall) -> Option { + alloy_todo!() + } + + fn parent_ptr(&self) -> Option { + match self.header.number { + 0 => None, + n => Some(BlockPtr::new( + self.header.parent_hash.into(), + (n - 1) as i32, + )), + } + } + + fn format(&self) -> String { + alloy_todo!() + } + + fn block_ptr(&self) -> BlockPtr { + alloy_todo!() + } +} + impl LightEthereumBlockExt for LightEthereumBlock { fn number(&self) -> BlockNumber { BlockNumber::try_from(self.number.unwrap().as_u64()).unwrap() diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 6763552da7a..3b5d301622b 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -88,6 +88,13 @@ pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { } } +#[macro_export] +macro_rules! alloy_todo { + () => { + todo!() + }; +} + pub fn alloy_transaction_receipt_to_web3_transaction_receipt( _receipt: Arc, ) -> Arc { From db61bacd6159849c969b71533bf09dc225514a73 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 26 Jun 2025 16:02:14 +0530 Subject: [PATCH 34/44] chain/ethereum: wrapper for Block --- chain/ethereum/src/trigger.rs | 15 ++++++--------- graph/src/components/ethereum/types.rs | 7 +++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index 9cce05e38c1..c5cc4edfef5 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -6,7 +6,6 @@ use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; use graph::prelude::web3::types::Address; -use graph::prelude::web3::types::Block; use graph::prelude::web3::types::Log; use graph::prelude::web3::types::Transaction; use graph::prelude::web3::types::TransactionReceipt; @@ -17,6 +16,7 @@ use graph::prelude::web3::types::U256; use graph::prelude::web3::types::U64; use graph::prelude::BlockNumber; use graph::prelude::BlockPtr; +use graph::prelude::LightEthereumBlock; use graph::prelude::{CheapClone, EthereumCall}; use graph::runtime::asc_new; use graph::runtime::gas::GasCounter; @@ -37,9 +37,6 @@ use crate::runtime::abi::AscEthereumTransaction_0_0_1; use crate::runtime::abi::AscEthereumTransaction_0_0_2; use crate::runtime::abi::AscEthereumTransaction_0_0_6; -// ETHDEP: This should be defined in only one place. -type LightEthereumBlock = Block; - static U256_DEFAULT: U256 = U256::zero(); pub enum MappingTrigger { @@ -412,11 +409,11 @@ impl TriggerData for EthereumTrigger { /// Ethereum block data. #[derive(Clone, Debug)] pub struct EthereumBlockData<'a> { - block: &'a Block, + block: &'a LightEthereumBlock, } -impl<'a> From<&'a Block> for EthereumBlockData<'a> { - fn from(block: &'a Block) -> EthereumBlockData<'a> { +impl<'a> From<&'a LightEthereumBlock> for EthereumBlockData<'a> { + fn from(block: &'a LightEthereumBlock) -> EthereumBlockData<'a> { EthereumBlockData { block } } } @@ -550,7 +547,7 @@ pub struct EthereumEventData<'a> { impl<'a> EthereumEventData<'a> { pub fn new( - block: &'a Block, + block: &'a LightEthereumBlock, tx: &'a Transaction, log: &'a Log, params: &'a [abi::DynSolParam], @@ -598,7 +595,7 @@ pub struct EthereumCallData<'a> { impl<'a> EthereumCallData<'a> { fn new( - block: &'a Block, + block: &'a LightEthereumBlock, transaction: &'a Transaction, call: &'a EthereumCall, inputs: &'a [abi::DynSolParam], diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index bd4d3d96756..b00a081c577 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -1,7 +1,7 @@ use alloy::rpc::types::trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}; use serde::{Deserialize, Serialize}; use std::{convert::TryFrom, sync::Arc}; -use web3::types::{Address, Block, Bytes, Log, Transaction, TransactionReceipt, H256, U256, U64}; +use web3::types::{Address, Bytes, Log, Transaction, TransactionReceipt, H256, U256, U64}; use crate::{ alloy_todo, @@ -12,7 +12,10 @@ use crate::{ util::conversions::{alloy_bytes_to_web3_bytes, alloy_u256_to_web3_u256, u64_to_web3_u256}, }; -pub type LightEthereumBlock = Block; +#[allow(dead_code)] +pub struct Block(web3::types::Block); + +pub type LightEthereumBlock = web3::types::Block; pub type LightEthereumBlockAlloy = AlloyBlock; pub trait LightEthereumBlockExt { From 445dc99144f7729b0e80339b958ab61083a67a9b Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 26 Jun 2025 17:10:29 +0530 Subject: [PATCH 35/44] chain/ethereum: wrap web3 block --- chain/ethereum/src/chain.rs | 4 +- chain/ethereum/src/codec.rs | 110 +++++++++--------- chain/ethereum/src/data_source.rs | 6 +- chain/ethereum/src/ethereum_adapter.rs | 58 ++++----- chain/ethereum/src/tests.rs | 14 ++- chain/ethereum/src/trigger.rs | 29 ++--- graph/src/blockchain/types.rs | 24 +++- graph/src/components/ethereum/mod.rs | 2 +- graph/src/components/ethereum/types.rs | 72 +++++++++++- graph/src/util/conversions.rs | 5 +- node/src/manager/commands/chain.rs | 6 +- store/test-store/src/block_store.rs | 14 ++- store/test-store/tests/postgres/chain_head.rs | 2 +- tests/src/fixture/ethereum.rs | 20 ++-- 14 files changed, 229 insertions(+), 137 deletions(-) diff --git a/chain/ethereum/src/chain.rs b/chain/ethereum/src/chain.rs index bcb2948ab01..c0eb5acb191 100644 --- a/chain/ethereum/src/chain.rs +++ b/chain/ethereum/src/chain.rs @@ -722,11 +722,11 @@ impl Block for BlockFinality { fn timestamp(&self) -> BlockTime { match self { BlockFinality::Final(block) => { - let ts = i64::try_from(block.timestamp.as_u64()).unwrap(); + let ts = i64::try_from(block.timestamp_u64()).unwrap(); BlockTime::since_epoch(ts, 0) } BlockFinality::NonFinal(block) => { - let ts = i64::try_from(block.ethereum_block.block.timestamp.as_u64()).unwrap(); + let ts = i64::try_from(block.ethereum_block.block.timestamp_u64()).unwrap(); BlockTime::since_epoch(ts, 0) } BlockFinality::Ptr(block) => block.timestamp, diff --git a/chain/ethereum/src/codec.rs b/chain/ethereum/src/codec.rs index 114982607ec..b12d0fd22e9 100644 --- a/chain/ethereum/src/codec.rs +++ b/chain/ethereum/src/codec.rs @@ -225,62 +225,64 @@ impl TryInto for &Block { format_err!("block header should always be present from gRPC Firehose") })?; + let web3_block = web3::types::Block { + hash: Some(self.hash.try_decode_proto("block hash")?), + number: Some(U64::from(self.number)), + author: header.coinbase.try_decode_proto("author / coinbase")?, + parent_hash: header.parent_hash.try_decode_proto("parent hash")?, + uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?, + state_root: header.state_root.try_decode_proto("state root")?, + transactions_root: header + .transactions_root + .try_decode_proto("transactions root")?, + receipts_root: header.receipt_root.try_decode_proto("receipt root")?, + gas_used: U256::from(header.gas_used), + gas_limit: U256::from(header.gas_limit), + base_fee_per_gas: Some( + header + .base_fee_per_gas + .as_ref() + .map_or_else(U256::default, |v| v.into()), + ), + extra_data: Bytes::from(header.extra_data.clone()), + logs_bloom: match &header.logs_bloom.len() { + 0 => None, + _ => Some(header.logs_bloom.try_decode_proto("logs bloom")?), + }, + timestamp: header + .timestamp + .as_ref() + .map_or_else(U256::default, |v| U256::from(v.seconds)), + difficulty: header + .difficulty + .as_ref() + .map_or_else(U256::default, |v| v.into()), + total_difficulty: Some( + header + .total_difficulty + .as_ref() + .map_or_else(U256::default, |v| v.into()), + ), + // FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?) + seal_fields: vec![], + uncles: self + .uncles + .iter() + .map(|u| u.hash.try_decode_proto("uncle hash")) + .collect::, _>>()?, + transactions: self + .transaction_traces + .iter() + .map(|t| TransactionTraceAt::new(t, self).try_into()) + .collect::, Error>>()?, + size: Some(U256::from(self.size)), + mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?), + nonce: Some(H64::from_low_u64_be(header.nonce)), + }; + let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(LightEthereumBlock { - hash: Some(self.hash.try_decode_proto("block hash")?), - number: Some(U64::from(self.number)), - author: header.coinbase.try_decode_proto("author / coinbase")?, - parent_hash: header.parent_hash.try_decode_proto("parent hash")?, - uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?, - state_root: header.state_root.try_decode_proto("state root")?, - transactions_root: header - .transactions_root - .try_decode_proto("transactions root")?, - receipts_root: header.receipt_root.try_decode_proto("receipt root")?, - gas_used: U256::from(header.gas_used), - gas_limit: U256::from(header.gas_limit), - base_fee_per_gas: Some( - header - .base_fee_per_gas - .as_ref() - .map_or_else(U256::default, |v| v.into()), - ), - extra_data: Bytes::from(header.extra_data.clone()), - logs_bloom: match &header.logs_bloom.len() { - 0 => None, - _ => Some(header.logs_bloom.try_decode_proto("logs bloom")?), - }, - timestamp: header - .timestamp - .as_ref() - .map_or_else(U256::default, |v| U256::from(v.seconds)), - difficulty: header - .difficulty - .as_ref() - .map_or_else(U256::default, |v| v.into()), - total_difficulty: Some( - header - .total_difficulty - .as_ref() - .map_or_else(U256::default, |v| v.into()), - ), - // FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?) - seal_fields: vec![], - uncles: self - .uncles - .iter() - .map(|u| u.hash.try_decode_proto("uncle hash")) - .collect::, _>>()?, - transactions: self - .transaction_traces - .iter() - .map(|t| TransactionTraceAt::new(t, self).try_into()) - .collect::, Error>>()?, - size: Some(U256::from(self.size)), - mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?), - nonce: Some(H64::from_low_u64_be(header.nonce)), - }), + block: Arc::new(LightEthereumBlock::new(web3_block)), transaction_receipts: self .transaction_traces .iter() diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index 551ee21f246..8e7fe606f42 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -747,13 +747,13 @@ impl DataSource { // See also ca0edc58-0ec5-4c89-a7dd-2241797f5e50. // There is another special case in zkSync-era, where the transaction hash in this case would be zero // See https://docs.zksync.io/zk-stack/concepts/blocks.html#fictive-l2-block-finalizing-the-batch - let transaction = if log.transaction_hash == block.hash + let transaction = if log.transaction_hash == block.hash_h256() || log.transaction_hash == Some(H256::zero()) { Transaction { hash: log.transaction_hash.unwrap(), - block_hash: block.hash, - block_number: block.number, + block_hash: block.hash_h256(), + block_number: block.number_web3_u64(), transaction_index: log.transaction_index, from: Some(H160::zero()), ..Transaction::default() diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index fc039abbbef..669c9b9350e 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -44,8 +44,8 @@ use graph::prelude::{ use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; -use graph::util::conversions::alloy_block_to_web3_block; -use graph::util::conversions::alloy_block_to_web3_block_arc; +use graph::util::conversions::alloy_block_to_block; +use graph::util::conversions::alloy_block_to_block_arc; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ @@ -1348,7 +1348,7 @@ impl EthereumAdapterTrait for EthereumAdapter { if block.transactions.is_empty() { trace!(logger, "Block {} contains no transactions", block_hash); return Ok(EthereumBlock { - block: Arc::new(alloy_block_to_web3_block(block)), + block: Arc::new(alloy_block_to_block(block)), transaction_receipts: Vec::new(), }); } @@ -1367,7 +1367,7 @@ impl EthereumAdapterTrait for EthereumAdapter { fetch_receipts_with_retry(alloy, hashes, block_hash, logger, supports_block_receipts) .await .map(|transaction_receipts| EthereumBlock { - block: Arc::new(alloy_block_to_web3_block(block)), + block: Arc::new(alloy_block_to_block(block)), transaction_receipts: transaction_receipts .into_iter() .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)) @@ -1647,7 +1647,7 @@ impl EthereumAdapterTrait for EthereumAdapter { .await?; let upsert_blocks: Vec<_> = new_blocks .iter() - .map(|block| BlockFinality::Final(alloy_block_to_web3_block_arc(block.clone()))) + .map(|block| BlockFinality::Final(alloy_block_to_block_arc(block.clone()))) .collect(); let block_refs: Vec<_> = upsert_blocks .iter() @@ -1802,7 +1802,7 @@ pub(crate) async fn blocks_with_triggers( .map( move |block| match triggers_by_block.remove(&(block.header.number() as BlockNumber)) { Some(triggers) => Ok(BlockWithTriggers::new( - BlockFinality::Final(alloy_block_to_web3_block_arc(block)), + BlockFinality::Final(alloy_block_to_block_arc(block)), triggers, &logger2, )), @@ -1875,9 +1875,8 @@ pub(crate) async fn get_calls( .calls_in_block( &logger, subgraph_metrics.clone(), - BlockNumber::try_from(ethereum_block.block.number.unwrap().as_u64()) - .unwrap(), - h256_to_b256(ethereum_block.block.hash.unwrap()), + ethereum_block.block.number(), + h256_to_b256(ethereum_block.block.hash_h256().unwrap()), ) .await? }; @@ -2061,7 +2060,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions( let transactions: Vec<&Transaction> = { match &block.block { BlockFinality::Final(ref block) => block - .transactions + .transactions() .iter() .filter(|transaction| transaction_hashes.contains(&transaction.hash)) .collect(), @@ -2626,12 +2625,14 @@ mod tests { EthereumBlockWithCalls, }; use graph::blockchain::BlockPtr; + use graph::components::ethereum::Block; use graph::prelude::alloy::primitives::B256; use graph::prelude::alloy::providers::mock::Asserter; use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; + use graph::prelude::web3::types::Block as Web3Block; use graph::prelude::web3::types::U64; - use graph::prelude::web3::types::{Address, Block, Bytes, H256}; + use graph::prelude::web3::types::{Address, Bytes, H256}; use graph::prelude::EthereumCall; use jsonrpc_core::serde_json::{self, Value}; use std::collections::HashSet; @@ -2640,13 +2641,15 @@ mod tests { #[test] fn parse_block_triggers_every_block() { + let web3_block = Web3Block { + hash: Some(hash(2)), + number: Some(U64::from(2)), + ..Default::default() + }; + let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }), + block: Arc::new(Block::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2783,13 +2786,14 @@ mod tests { #[test] fn parse_block_triggers_specific_call_not_found() { + let web3_block = Web3Block { + hash: Some(hash(2)), + number: Some(U64::from(2)), + ..Default::default() + }; let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }), + block: Arc::new(Block::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2815,13 +2819,15 @@ mod tests { #[test] fn parse_block_triggers_specific_call_found() { + let web3_block = Web3Block { + hash: Some(hash(2)), + number: Some(U64::from(2)), + ..Default::default() + }; + let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }), + block: Arc::new(Block::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index 00873f8ea87..fe7049cabf8 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -2,9 +2,13 @@ use std::sync::Arc; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger}, + components::ethereum::Block, prelude::{ - web3::types::{Address, Bytes, Log, H160, H256, U64}, - EthereumCall, LightEthereumBlock, + web3::{ + self, + types::{Address, Bytes, Log, Transaction, H160, H256, U64}, + }, + EthereumCall, }, slog::{self, o, Logger}, }; @@ -92,13 +96,14 @@ fn test_trigger_ordering() { let logger = Logger::root(slog::Discard, o!()); - let mut b: LightEthereumBlock = Default::default(); + let mut b: web3::types::Block = Default::default(); // This is necessary because inside of BlockWithTriggers::new // there's a log for both fields. So just using Default above // gives None on them. b.number = Some(Default::default()); b.hash = Some(Default::default()); + let b = Block::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( @@ -190,13 +195,14 @@ fn test_trigger_dedup() { let logger = Logger::root(slog::Discard, o!()); - let mut b: LightEthereumBlock = Default::default(); + let mut b: web3::types::Block = Default::default(); // This is necessary because inside of BlockWithTriggers::new // there's a log for both fields. So just using Default above // gives None on them. b.number = Some(Default::default()); b.hash = Some(Default::default()); + let b = Block::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index c5cc4edfef5..489f3e2768c 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -420,66 +420,67 @@ impl<'a> From<&'a LightEthereumBlock> for EthereumBlockData<'a> { impl<'a> EthereumBlockData<'a> { pub fn hash(&self) -> &H256 { - self.block.hash.as_ref().unwrap() + self.block.inner().hash.as_ref().unwrap() } pub fn parent_hash(&self) -> &H256 { - &self.block.parent_hash + &self.block.inner().parent_hash } pub fn uncles_hash(&self) -> &H256 { - &self.block.uncles_hash + &self.block.inner().uncles_hash } pub fn author(&self) -> &H160 { - &self.block.author + &self.block.inner().author } pub fn state_root(&self) -> &H256 { - &self.block.state_root + &self.block.inner().state_root } pub fn transactions_root(&self) -> &H256 { - &self.block.transactions_root + &self.block.inner().transactions_root } pub fn receipts_root(&self) -> &H256 { - &self.block.receipts_root + &self.block.inner().receipts_root } pub fn number(&self) -> U64 { - self.block.number.unwrap() + self.block.inner().number.unwrap() } pub fn gas_used(&self) -> &U256 { - &self.block.gas_used + &self.block.inner().gas_used } pub fn gas_limit(&self) -> &U256 { - &self.block.gas_limit + &self.block.inner().gas_limit } pub fn timestamp(&self) -> &U256 { - &self.block.timestamp + &self.block.inner().timestamp } pub fn difficulty(&self) -> &U256 { - &self.block.difficulty + &self.block.inner().difficulty } pub fn total_difficulty(&self) -> &U256 { self.block + .inner() .total_difficulty .as_ref() .unwrap_or(&U256_DEFAULT) } pub fn size(&self) -> &Option { - &self.block.size + &self.block.inner().size } pub fn base_fee_per_gas(&self) -> &Option { - &self.block.base_fee_per_gas + &self.block.inner().base_fee_per_gas } } diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index 2e1c31add2d..ecb0d171973 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -10,7 +10,9 @@ use serde::{Deserialize, Deserializer}; use std::convert::TryFrom; use std::time::Duration; use std::{fmt, str::FromStr}; -use web3::types::{Block, H256, U256, U64}; +use web3::types::{Block as Web3Block, H256, U256, U64}; + +use crate::components::ethereum::Block; use crate::cheap_clone::CheapClone; use crate::components::store::BlockNumber; @@ -216,14 +218,26 @@ impl slog::Value for BlockPtr { } } -impl From> for BlockPtr { - fn from(b: Block) -> BlockPtr { +impl From for BlockPtr { + fn from(b: Block) -> BlockPtr { + BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) + } +} + +impl From<&Block> for BlockPtr { + fn from(b: &Block) -> BlockPtr { + BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) + } +} + +impl From> for BlockPtr { + fn from(b: Web3Block) -> BlockPtr { BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) } } -impl<'a, T> From<&'a Block> for BlockPtr { - fn from(b: &'a Block) -> BlockPtr { +impl<'a, T> From<&'a Web3Block> for BlockPtr { + fn from(b: &'a Web3Block) -> BlockPtr { BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) } } diff --git a/graph/src/components/ethereum/mod.rs b/graph/src/components/ethereum/mod.rs index 45f1f5d98ad..4a26fd7e573 100644 --- a/graph/src/components/ethereum/mod.rs +++ b/graph/src/components/ethereum/mod.rs @@ -1,6 +1,6 @@ mod types; pub use self::types::{ - evaluate_transaction_status, EthereumBlock, EthereumBlockWithCalls, EthereumCall, + evaluate_transaction_status, Block, EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, }; diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index b00a081c577..5505401e4d5 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -13,10 +13,40 @@ use crate::{ }; #[allow(dead_code)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct Block(web3::types::Block); -pub type LightEthereumBlock = web3::types::Block; -pub type LightEthereumBlockAlloy = AlloyBlock; +impl Block { + pub fn new(block: web3::types::Block) -> Self { + Self(block) + } + + pub fn hash_h256(&self) -> Option { + self.0.hash + } + + pub fn number_u64(&self) -> Option { + self.0.number.map(|n| n.as_u64()) + } + + pub fn number_web3_u64(&self) -> Option { + self.0.number + } + + pub fn timestamp_u64(&self) -> u64 { + self.0.timestamp.as_u64() + } + + pub fn transactions(&self) -> &[Transaction] { + &self.0.transactions + } + + pub fn inner(&self) -> &web3::types::Block { + &self.0 + } +} + +pub type LightEthereumBlock = Block; pub trait LightEthereumBlockExt { fn number(&self) -> BlockNumber; @@ -28,7 +58,7 @@ pub trait LightEthereumBlockExt { fn timestamp(&self) -> BlockTime; } -impl LightEthereumBlockExt for LightEthereumBlockAlloy { +impl LightEthereumBlockExt for AlloyBlock { fn number(&self) -> BlockNumber { alloy_todo!() } @@ -65,6 +95,36 @@ impl LightEthereumBlockExt for LightEthereumBlockAlloy { } impl LightEthereumBlockExt for LightEthereumBlock { + fn number(&self) -> BlockNumber { + self.0.number() + } + + fn transaction_for_log(&self, log: &Log) -> Option { + self.0.transaction_for_log(log) + } + + fn transaction_for_call(&self, call: &EthereumCall) -> Option { + self.0.transaction_for_call(call) + } + + fn parent_ptr(&self) -> Option { + self.0.parent_ptr() + } + + fn format(&self) -> String { + self.0.format() + } + + fn block_ptr(&self) -> BlockPtr { + self.0.block_ptr() + } + + fn timestamp(&self) -> BlockTime { + self.0.timestamp() + } +} + +impl LightEthereumBlockExt for web3::types::Block { fn number(&self) -> BlockNumber { BlockNumber::try_from(self.number.unwrap().as_u64()).unwrap() } @@ -146,7 +206,7 @@ pub fn evaluate_transaction_status(receipt_status: Option) -> bool { .unwrap_or(true) } -#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct EthereumBlock { pub block: Arc, pub transaction_receipts: Vec>, @@ -209,13 +269,13 @@ impl EthereumCall { impl From for BlockPtr { fn from(b: EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash.unwrap(), b.block.number.unwrap().as_u64())) + BlockPtr::from((b.block.hash_h256().unwrap(), b.block.number())) } } impl<'a> From<&'a EthereumBlock> for BlockPtr { fn from(b: &'a EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash.unwrap(), b.block.number.unwrap().as_u64())) + BlockPtr::from((b.block.hash_h256().unwrap(), b.block.number())) } } diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 3b5d301622b..867bf5ce5b7 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use web3::types::Bytes; +use crate::components::ethereum::Block; use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; use crate::prelude::alloy::rpc::types::{ Block as AlloyBlock, Log as AlloyLog, TransactionReceipt as AlloyTransactionReceipt, @@ -102,13 +103,13 @@ pub fn alloy_transaction_receipt_to_web3_transaction_receipt( } /// Converts alloy Block to web3 Block -pub fn alloy_block_to_web3_block_arc(_block: Arc) -> Arc> { +pub fn alloy_block_to_block_arc(_block: Arc) -> Arc { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) } -pub fn alloy_block_to_web3_block(_block: AlloyBlock) -> Web3Block { +pub fn alloy_block_to_block(_block: AlloyBlock) -> Block { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) diff --git a/node/src/manager/commands/chain.rs b/node/src/manager/commands/chain.rs index 595d77b7eab..993c265da3c 100644 --- a/node/src/manager/commands/chain.rs +++ b/node/src/manager/commands/chain.rs @@ -14,7 +14,7 @@ use graph::prelude::BlockNumber; use graph::prelude::ChainStore as _; use graph::prelude::{anyhow, anyhow::bail}; use graph::slog::Logger; -use graph::util::conversions::alloy_block_to_web3_block; +use graph::util::conversions::alloy_block_to_block; use graph::{ components::store::BlockStore as _, components::store::ChainHeadStore as _, prelude::anyhow::Error, @@ -279,9 +279,7 @@ pub async fn ingest( let hash = block.header.hash; let number = block.header.number; // For inserting the block, it doesn't matter whether the block is final or not. - let block = Arc::new(BlockFinality::Final(Arc::new(alloy_block_to_web3_block( - block, - )))); + let block = Arc::new(BlockFinality::Final(Arc::new(alloy_block_to_block(block)))); chain_store.upsert_block(block).await?; let hash = hash.into(); diff --git a/store/test-store/src/block_store.rs b/store/test-store/src/block_store.rs index 092be0274a8..f6a379b044b 100644 --- a/store/test-store/src/block_store.rs +++ b/store/test-store/src/block_store.rs @@ -1,6 +1,8 @@ use std::{convert::TryFrom, str::FromStr, sync::Arc}; use graph::blockchain::{BlockTime, ChainIdentifier}; +use graph::components::ethereum::Block; +use graph::prelude::web3; use lazy_static::lazy_static; use graph::components::store::BlockStore; @@ -8,10 +10,10 @@ use graph::{ blockchain::Block as BlockchainBlock, prelude::{ serde_json, web3::types::H256, web3::types::U256, BlockHash, BlockNumber, BlockPtr, - EthereumBlock, LightEthereumBlock, + EthereumBlock, }, }; -use graph_chain_ethereum::codec::{Block, BlockHeader}; +use graph_chain_ethereum::codec::{Block as FirehoseBlock, BlockHeader}; use prost_types::Timestamp; use crate::{GENESIS_PTR, NETWORK_VERSION}; @@ -105,7 +107,7 @@ impl FakeBlock { pub fn as_ethereum_block(&self) -> EthereumBlock { let parent_hash = H256::from_str(self.parent_hash.as_str()).expect("invalid parent hash"); - let mut block = LightEthereumBlock::default(); + let mut block = web3::types::Block::default(); block.number = Some(self.number.into()); block.parent_hash = parent_hash; block.hash = Some(H256(self.block_hash().as_slice().try_into().unwrap())); @@ -114,13 +116,13 @@ impl FakeBlock { } EthereumBlock { - block: Arc::new(block), + block: Arc::new(Block::new(block)), transaction_receipts: Vec::new(), } } - pub fn as_firehose_block(&self) -> Block { - let mut block = Block::default(); + pub fn as_firehose_block(&self) -> FirehoseBlock { + let mut block = FirehoseBlock::default(); block.hash = self.hash.clone().into_bytes(); block.number = self.number as u64; diff --git a/store/test-store/tests/postgres/chain_head.rs b/store/test-store/tests/postgres/chain_head.rs index 8a09b845392..0d8b92569e2 100644 --- a/store/test-store/tests/postgres/chain_head.rs +++ b/store/test-store/tests/postgres/chain_head.rs @@ -318,7 +318,7 @@ fn check_ancestor( } let act_block = json::from_value::(act.0)?; - let act_hash = format!("{:x}", act_block.block.hash.unwrap()); + let act_hash = format!("{:x}", act_block.block.hash_h256().unwrap()); let exp_hash = &exp.hash; if &act_hash != exp_hash { diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index 476bc73498b..bb0138a03d0 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -12,11 +12,12 @@ use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation use graph::blockchain::client::ChainClient; use graph::blockchain::{BlockPtr, Trigger, TriggersAdapterSelector}; use graph::cheap_clone::CheapClone; +use graph::components::ethereum::Block; use graph::data_source::subgraph; use graph::prelude::web3::types::H256; use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Log, Transaction, H160}; -use graph::prelude::{tiny_keccak, DeploymentHash, Entity, LightEthereumBlock, ENV_VARS}; +use graph::prelude::{tiny_keccak, web3, DeploymentHash, Entity, ENV_VARS}; use graph::schema::EntityType; use graph_chain_ethereum::network::EthereumNetworkAdapters; use graph_chain_ethereum::trigger::LogRef; @@ -78,12 +79,13 @@ pub async fn chain( pub fn genesis() -> BlockWithTriggers { let ptr = test_ptr(0); + let block: web3::types::Block = web3::types::Block { + hash: Some(H256::from_slice(ptr.hash.as_slice())), + number: Some(U64::from(ptr.number)), + ..Default::default() + }; BlockWithTriggers:: { - block: BlockFinality::Final(Arc::new(LightEthereumBlock { - hash: Some(H256::from_slice(ptr.hash.as_slice())), - number: Some(U64::from(ptr.number)), - ..Default::default() - })), + block: BlockFinality::Final(Arc::new(Block::new(block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, @@ -127,13 +129,13 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers { - block: BlockFinality::Final(Arc::new(LightEthereumBlock { + block: BlockFinality::Final(Arc::new(Block::new(web3::types::Block { hash: Some(H256::from_slice(ptr.hash.as_slice())), number: Some(U64::from(ptr.number)), parent_hash: H256::from_slice(parent_ptr.hash.as_slice()), - transactions, + transactions: transactions.clone(), ..Default::default() - })), + }))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, From 973f48e56fadb65de3abf4c37a919035c6f66e0b Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 26 Jun 2025 17:37:51 +0530 Subject: [PATCH 36/44] use alloy block --- chain/ethereum/src/codec.rs | 120 +++++++++++++------------ chain/ethereum/src/ethereum_adapter.rs | 52 ++++++----- chain/ethereum/src/tests.rs | 27 ++++-- graph/src/blockchain/types.rs | 10 +-- graph/src/components/ethereum/mod.rs | 2 +- graph/src/components/ethereum/types.rs | 26 +++--- graph/src/util/conversions.rs | 6 +- store/test-store/src/block_store.rs | 22 +++-- tests/src/fixture/ethereum.rs | 41 +++++---- 9 files changed, 173 insertions(+), 133 deletions(-) diff --git a/chain/ethereum/src/codec.rs b/chain/ethereum/src/codec.rs index b12d0fd22e9..d50598ab37e 100644 --- a/chain/ethereum/src/codec.rs +++ b/chain/ethereum/src/codec.rs @@ -4,12 +4,15 @@ mod pbcodec; use anyhow::format_err; use graph::{ + alloy_todo, blockchain::{ self, Block as BlockchainBlock, BlockPtr, BlockTime, ChainStoreBlock, ChainStoreData, }, prelude::{ - web3, - web3::types::{Bytes, H160, H2048, H256, H64, U256, U64}, + web3::{ + self, + types::{Bytes, H160, H2048, H256, U256, U64}, + }, BlockNumber, Error, EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, }, @@ -225,64 +228,65 @@ impl TryInto for &Block { format_err!("block header should always be present from gRPC Firehose") })?; - let web3_block = web3::types::Block { - hash: Some(self.hash.try_decode_proto("block hash")?), - number: Some(U64::from(self.number)), - author: header.coinbase.try_decode_proto("author / coinbase")?, - parent_hash: header.parent_hash.try_decode_proto("parent hash")?, - uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?, - state_root: header.state_root.try_decode_proto("state root")?, - transactions_root: header - .transactions_root - .try_decode_proto("transactions root")?, - receipts_root: header.receipt_root.try_decode_proto("receipt root")?, - gas_used: U256::from(header.gas_used), - gas_limit: U256::from(header.gas_limit), - base_fee_per_gas: Some( - header - .base_fee_per_gas - .as_ref() - .map_or_else(U256::default, |v| v.into()), - ), - extra_data: Bytes::from(header.extra_data.clone()), - logs_bloom: match &header.logs_bloom.len() { - 0 => None, - _ => Some(header.logs_bloom.try_decode_proto("logs bloom")?), - }, - timestamp: header - .timestamp - .as_ref() - .map_or_else(U256::default, |v| U256::from(v.seconds)), - difficulty: header - .difficulty - .as_ref() - .map_or_else(U256::default, |v| v.into()), - total_difficulty: Some( - header - .total_difficulty - .as_ref() - .map_or_else(U256::default, |v| v.into()), - ), - // FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?) - seal_fields: vec![], - uncles: self - .uncles - .iter() - .map(|u| u.hash.try_decode_proto("uncle hash")) - .collect::, _>>()?, - transactions: self - .transaction_traces - .iter() - .map(|t| TransactionTraceAt::new(t, self).try_into()) - .collect::, Error>>()?, - size: Some(U256::from(self.size)), - mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?), - nonce: Some(H64::from_low_u64_be(header.nonce)), - }; - + // let web3_block = web3::types::Block { + // hash: Some(self.hash.try_decode_proto("block hash")?), + // number: Some(U64::from(self.number)), + // author: header.coinbase.try_decode_proto("author / coinbase")?, + // parent_hash: header.parent_hash.try_decode_proto("parent hash")?, + // uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?, + // state_root: header.state_root.try_decode_proto("state root")?, + // transactions_root: header + // .transactions_root + // .try_decode_proto("transactions root")?, + // receipts_root: header.receipt_root.try_decode_proto("receipt root")?, + // gas_used: U256::from(header.gas_used), + // gas_limit: U256::from(header.gas_limit), + // base_fee_per_gas: Some( + // header + // .base_fee_per_gas + // .as_ref() + // .map_or_else(U256::default, |v| v.into()), + // ), + // extra_data: Bytes::from(header.extra_data.clone()), + // logs_bloom: match &header.logs_bloom.len() { + // 0 => None, + // _ => Some(header.logs_bloom.try_decode_proto("logs bloom")?), + // }, + // timestamp: header + // .timestamp + // .as_ref() + // .map_or_else(U256::default, |v| U256::from(v.seconds)), + // difficulty: header + // .difficulty + // .as_ref() + // .map_or_else(U256::default, |v| v.into()), + // total_difficulty: Some( + // header + // .total_difficulty + // .as_ref() + // .map_or_else(U256::default, |v| v.into()), + // ), + // // FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?) + // seal_fields: vec![], + // uncles: self + // .uncles + // .iter() + // .map(|u| u.hash.try_decode_proto("uncle hash")) + // .collect::, _>>()?, + // transactions: self + // .transaction_traces + // .iter() + // .map(|t| TransactionTraceAt::new(t, self).try_into()) + // .collect::, Error>>()?, + // size: Some(U256::from(self.size)), + // mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?), + // nonce: Some(H64::from_low_u64_be(header.nonce)), + // }; + + #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(LightEthereumBlock::new(web3_block)), + block: Arc::new(LightEthereumBlock::new(alloy_todo!())), transaction_receipts: self .transaction_traces .iter() diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 669c9b9350e..09701162f6f 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -2624,14 +2624,13 @@ mod tests { check_block_receipt_support, parse_block_triggers, EthereumBlock, EthereumBlockFilter, EthereumBlockWithCalls, }; + use graph::alloy_todo; use graph::blockchain::BlockPtr; - use graph::components::ethereum::Block; + use graph::components::ethereum::BlockWrapper; use graph::prelude::alloy::primitives::B256; use graph::prelude::alloy::providers::mock::Asserter; use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; - use graph::prelude::web3::types::Block as Web3Block; - use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Bytes, H256}; use graph::prelude::EthereumCall; use jsonrpc_core::serde_json::{self, Value}; @@ -2641,15 +2640,17 @@ mod tests { #[test] fn parse_block_triggers_every_block() { - let web3_block = Web3Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }; - + // let web3_block = Web3Block { + // hash: Some(hash(2)), + // number: Some(U64::from(2)), + // ..Default::default() + // }; + let web3_block = alloy_todo!(); + + #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block::new(web3_block)), + block: Arc::new(BlockWrapper::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2786,14 +2787,17 @@ mod tests { #[test] fn parse_block_triggers_specific_call_not_found() { - let web3_block = Web3Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }; + // let web3_block = Web3Block { + // hash: Some(hash(2)), + // number: Some(U64::from(2)), + // ..Default::default() + // }; + let web3_block = alloy_todo!(); + + #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block::new(web3_block)), + block: Arc::new(BlockWrapper::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2819,15 +2823,17 @@ mod tests { #[test] fn parse_block_triggers_specific_call_found() { - let web3_block = Web3Block { - hash: Some(hash(2)), - number: Some(U64::from(2)), - ..Default::default() - }; - + // let web3_block = Web3Block { + // hash: Some(hash(2)), + // number: Some(U64::from(2)), + // ..Default::default() + // }; + let web3_block = alloy_todo!(); + + #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(Block::new(web3_block)), + block: Arc::new(BlockWrapper::new(web3_block)), ..Default::default() }, calls: Some(vec![EthereumCall { diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index fe7049cabf8..9aa75c10fa5 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -1,8 +1,9 @@ use std::sync::Arc; use graph::{ + alloy_todo, blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger}, - components::ethereum::Block, + components::ethereum::BlockWrapper, prelude::{ web3::{ self, @@ -96,14 +97,17 @@ fn test_trigger_ordering() { let logger = Logger::root(slog::Discard, o!()); - let mut b: web3::types::Block = Default::default(); + // let mut b: web3::types::Block = Default::default(); - // This is necessary because inside of BlockWithTriggers::new - // there's a log for both fields. So just using Default above - // gives None on them. - b.number = Some(Default::default()); - b.hash = Some(Default::default()); - let b = Block::new(b); + // // This is necessary because inside of BlockWithTriggers::new + // // there's a log for both fields. So just using Default above + // // gives None on them. + // b.number = Some(Default::default()); + // b.hash = Some(Default::default()); + let b = alloy_todo!(); + + #[allow(unreachable_code)] + let b = BlockWrapper::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( @@ -202,7 +206,12 @@ fn test_trigger_dedup() { // gives None on them. b.number = Some(Default::default()); b.hash = Some(Default::default()); - let b = Block::new(b); + + #[allow(unused_variables)] + let b = alloy_todo!(); + + #[allow(unreachable_code)] + let b = BlockWrapper::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index ecb0d171973..c4b538f1188 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -12,7 +12,7 @@ use std::time::Duration; use std::{fmt, str::FromStr}; use web3::types::{Block as Web3Block, H256, U256, U64}; -use crate::components::ethereum::Block; +use crate::components::ethereum::BlockWrapper; use crate::cheap_clone::CheapClone; use crate::components::store::BlockNumber; @@ -218,14 +218,14 @@ impl slog::Value for BlockPtr { } } -impl From for BlockPtr { - fn from(b: Block) -> BlockPtr { +impl From for BlockPtr { + fn from(b: BlockWrapper) -> BlockPtr { BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) } } -impl From<&Block> for BlockPtr { - fn from(b: &Block) -> BlockPtr { +impl From<&BlockWrapper> for BlockPtr { + fn from(b: &BlockWrapper) -> BlockPtr { BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) } } diff --git a/graph/src/components/ethereum/mod.rs b/graph/src/components/ethereum/mod.rs index 4a26fd7e573..bca1438cf24 100644 --- a/graph/src/components/ethereum/mod.rs +++ b/graph/src/components/ethereum/mod.rs @@ -1,6 +1,6 @@ mod types; pub use self::types::{ - evaluate_transaction_status, Block, EthereumBlock, EthereumBlockWithCalls, EthereumCall, + evaluate_transaction_status, BlockWrapper, EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, }; diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index 5505401e4d5..19ac22668cc 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -14,39 +14,45 @@ use crate::{ #[allow(dead_code)] #[derive(Debug, Default, Deserialize, Serialize)] -pub struct Block(web3::types::Block); +pub struct BlockWrapper(AlloyBlock); -impl Block { - pub fn new(block: web3::types::Block) -> Self { +impl BlockWrapper { + pub fn new(block: AlloyBlock) -> Self { Self(block) } pub fn hash_h256(&self) -> Option { - self.0.hash + alloy_todo!() + // self.0.hash } pub fn number_u64(&self) -> Option { - self.0.number.map(|n| n.as_u64()) + alloy_todo!() + // self.0.number.map(|n| n.as_u64()) } pub fn number_web3_u64(&self) -> Option { - self.0.number + alloy_todo!() + // Some(u64_to_web3_u64(self.0.header.number)) } pub fn timestamp_u64(&self) -> u64 { - self.0.timestamp.as_u64() + alloy_todo!() + // self.0.timestamp.as_u64() } pub fn transactions(&self) -> &[Transaction] { - &self.0.transactions + alloy_todo!() + // &self.0.transactions } pub fn inner(&self) -> &web3::types::Block { - &self.0 + alloy_todo!() + // &self.0 } } -pub type LightEthereumBlock = Block; +pub type LightEthereumBlock = BlockWrapper; pub trait LightEthereumBlockExt { fn number(&self) -> BlockNumber; diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 867bf5ce5b7..e385d7eca76 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use web3::types::Bytes; -use crate::components::ethereum::Block; +use crate::components::ethereum::BlockWrapper; use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; use crate::prelude::alloy::rpc::types::{ Block as AlloyBlock, Log as AlloyLog, TransactionReceipt as AlloyTransactionReceipt, @@ -103,13 +103,13 @@ pub fn alloy_transaction_receipt_to_web3_transaction_receipt( } /// Converts alloy Block to web3 Block -pub fn alloy_block_to_block_arc(_block: Arc) -> Arc { +pub fn alloy_block_to_block_arc(_block: Arc) -> Arc { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) } -pub fn alloy_block_to_block(_block: AlloyBlock) -> Block { +pub fn alloy_block_to_block(_block: AlloyBlock) -> BlockWrapper { unimplemented!( "Block conversion from alloy to web3 not yet implemented - will be done when needed" ) diff --git a/store/test-store/src/block_store.rs b/store/test-store/src/block_store.rs index f6a379b044b..7ac852f8a76 100644 --- a/store/test-store/src/block_store.rs +++ b/store/test-store/src/block_store.rs @@ -1,7 +1,8 @@ use std::{convert::TryFrom, str::FromStr, sync::Arc}; +use graph::alloy_todo; use graph::blockchain::{BlockTime, ChainIdentifier}; -use graph::components::ethereum::Block; +use graph::components::ethereum::BlockWrapper; use graph::prelude::web3; use lazy_static::lazy_static; @@ -107,16 +108,19 @@ impl FakeBlock { pub fn as_ethereum_block(&self) -> EthereumBlock { let parent_hash = H256::from_str(self.parent_hash.as_str()).expect("invalid parent hash"); - let mut block = web3::types::Block::default(); - block.number = Some(self.number.into()); - block.parent_hash = parent_hash; - block.hash = Some(H256(self.block_hash().as_slice().try_into().unwrap())); - if let Some(ts) = self.timestamp { - block.timestamp = ts; - } + // let mut block = web3::types::Block::default(); + // block.number = Some(self.number.into()); + // block.parent_hash = parent_hash; + // block.hash = Some(H256(self.block_hash().as_slice().try_into().unwrap())); + // if let Some(ts) = self.timestamp { + // block.timestamp = ts; + // } + + let block = alloy_todo!(); + #[allow(unreachable_code)] EthereumBlock { - block: Arc::new(Block::new(block)), + block: Arc::new(BlockWrapper::new(block)), transaction_receipts: Vec::new(), } } diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index bb0138a03d0..b8868b3b58f 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -6,19 +6,19 @@ use super::{ test_ptr, CommonChainConfig, MutexBlockStreamBuilder, NoopAdapterSelector, NoopRuntimeAdapterBuilder, StaticBlockRefetcher, StaticStreamBuilder, Stores, TestChain, }; -use graph::abi; use graph::blockchain::block_stream::BlockWithTriggers; use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation}; use graph::blockchain::client::ChainClient; use graph::blockchain::{BlockPtr, Trigger, TriggersAdapterSelector}; use graph::cheap_clone::CheapClone; -use graph::components::ethereum::Block; +use graph::components::ethereum::BlockWrapper; use graph::data_source::subgraph; use graph::prelude::web3::types::H256; use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Log, Transaction, H160}; use graph::prelude::{tiny_keccak, web3, DeploymentHash, Entity, ENV_VARS}; use graph::schema::EntityType; +use graph::{abi, alloy_todo}; use graph_chain_ethereum::network::EthereumNetworkAdapters; use graph_chain_ethereum::trigger::LogRef; use graph_chain_ethereum::Chain; @@ -78,14 +78,20 @@ pub async fn chain( } pub fn genesis() -> BlockWithTriggers { + #[allow(unused_variables)] let ptr = test_ptr(0); - let block: web3::types::Block = web3::types::Block { - hash: Some(H256::from_slice(ptr.hash.as_slice())), - number: Some(U64::from(ptr.number)), - ..Default::default() - }; + // let block: web3::types::Block = web3::types::Block { + // hash: Some(H256::from_slice(ptr.hash.as_slice())), + // number: Some(U64::from(ptr.number)), + // ..Default::default() + // }; + + #[allow(unused_variables)] + let block = alloy_todo!(); + + #[allow(unreachable_code)] BlockWithTriggers:: { - block: BlockFinality::Final(Arc::new(Block::new(block))), + block: BlockFinality::Final(Arc::new(BlockWrapper::new(block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, @@ -117,6 +123,7 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers parent_ptr.number); + #[allow(unused_variables)] // A 0x000.. transaction is used so `push_test_log` can use it let transactions = vec![Transaction { hash: H256::zero(), @@ -128,14 +135,18 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers { - block: BlockFinality::Final(Arc::new(Block::new(web3::types::Block { - hash: Some(H256::from_slice(ptr.hash.as_slice())), - number: Some(U64::from(ptr.number)), - parent_hash: H256::from_slice(parent_ptr.hash.as_slice()), - transactions: transactions.clone(), - ..Default::default() - }))), + block: BlockFinality::Final(Arc::new(BlockWrapper::new(web3_block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, From 0029b69b57852161b2a820b3ec870e1e781209bf Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 26 Jun 2025 19:25:50 +0530 Subject: [PATCH 37/44] Migrate transaction receipt to alloy --- chain/ethereum/src/codec.rs | 121 +++++++++--------- chain/ethereum/src/ethereum_adapter.rs | 9 +- chain/ethereum/src/runtime/abi.rs | 162 +++++++++++++++++++++++++ chain/ethereum/src/trigger.rs | 16 ++- graph/src/components/ethereum/types.rs | 9 +- graph/src/util/conversions.rs | 4 + runtime/wasm/src/to_from/external.rs | 22 ++++ 7 files changed, 267 insertions(+), 76 deletions(-) diff --git a/chain/ethereum/src/codec.rs b/chain/ethereum/src/codec.rs index d50598ab37e..45fcb8de57c 100644 --- a/chain/ethereum/src/codec.rs +++ b/chain/ethereum/src/codec.rs @@ -292,66 +292,67 @@ impl TryInto for &Block { .iter() .filter_map(|t| { t.receipt.as_ref().map(|r| { - Ok(web3::types::TransactionReceipt { - transaction_hash: t.hash.try_decode_proto("transaction hash")?, - transaction_index: U64::from(t.index), - block_hash: Some( - self.hash.try_decode_proto("transaction block hash")?, - ), - block_number: Some(U64::from(self.number)), - cumulative_gas_used: U256::from(r.cumulative_gas_used), - // FIXME (SF): What is the rule here about gas_used being None, when it's 0? - gas_used: Some(U256::from(t.gas_used)), - contract_address: { - match t.calls.len() { - 0 => None, - _ => { - match CallType::try_from(t.calls[0].call_type).map_err( - |_| { - graph::anyhow::anyhow!( - "invalid call type: {}", - t.calls[0].call_type, - ) - }, - )? { - CallType::Create => { - Some(t.calls[0].address.try_decode_proto( - "transaction contract address", - )?) - } - _ => None, - } - } - } - }, - logs: r - .logs - .iter() - .map(|l| LogAt::new(l, self, t).try_into()) - .collect::, Error>>()?, - status: TransactionTraceStatus::try_from(t.status) - .map_err(|_| { - graph::anyhow::anyhow!( - "invalid transaction trace status: {}", - t.status - ) - })? - .try_into()?, - root: match r.state_root.len() { - 0 => None, // FIXME (SF): should this instead map to [0;32]? - // FIXME (SF): if len < 32, what do we do? - _ => Some( - r.state_root.try_decode_proto("transaction state root")?, - ), - }, - logs_bloom: r - .logs_bloom - .try_decode_proto("transaction logs bloom")?, - from: t.from.try_decode_proto("transaction from")?, - to: get_to_address(t)?, - transaction_type: None, - effective_gas_price: None, - }) + // Ok(web3::types::TransactionReceipt { + // transaction_hash: t.hash.try_decode_proto("transaction hash")?, + // transaction_index: U64::from(t.index), + // block_hash: Some( + // self.hash.try_decode_proto("transaction block hash")?, + // ), + // block_number: Some(U64::from(self.number)), + // cumulative_gas_used: U256::from(r.cumulative_gas_used), + // // FIXME (SF): What is the rule here about gas_used being None, when it's 0? + // gas_used: Some(U256::from(t.gas_used)), + // contract_address: { + // match t.calls.len() { + // 0 => None, + // _ => { + // match CallType::try_from(t.calls[0].call_type).map_err( + // |_| { + // graph::anyhow::anyhow!( + // "invalid call type: {}", + // t.calls[0].call_type, + // ) + // }, + // )? { + // CallType::Create => { + // Some(t.calls[0].address.try_decode_proto( + // "transaction contract address", + // )?) + // } + // _ => None, + // } + // } + // } + // }, + // logs: r + // .logs + // .iter() + // .map(|l| LogAt::new(l, self, t).try_into()) + // .collect::, Error>>()?, + // status: TransactionTraceStatus::try_from(t.status) + // .map_err(|_| { + // graph::anyhow::anyhow!( + // "invalid transaction trace status: {}", + // t.status + // ) + // })? + // .try_into()?, + // root: match r.state_root.len() { + // 0 => None, // FIXME (SF): should this instead map to [0;32]? + // // FIXME (SF): if len < 32, what do we do? + // _ => Some( + // r.state_root.try_decode_proto("transaction state root")?, + // ), + // }, + // logs_bloom: r + // .logs_bloom + // .try_decode_proto("transaction logs bloom")?, + // from: t.from.try_decode_proto("transaction from")?, + // to: get_to_address(t)?, + // transaction_type: None, + // effective_gas_price: None, + // }) + Ok(alloy_todo!()) }) }) .collect::, Error>>()? diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 09701162f6f..09b174c6b31 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -37,8 +37,7 @@ use graph::prelude::{ }, transports::{RpcError, TransportErrorKind}, }, - alloy_log_to_web3_log, alloy_transaction_receipt_to_web3_transaction_receipt, - h160_to_alloy_address, h256_to_b256, + alloy_log_to_web3_log, h160_to_alloy_address, h256_to_b256, tokio::try_join, }; use graph::slog::o; @@ -1370,7 +1369,7 @@ impl EthereumAdapterTrait for EthereumAdapter { block: Arc::new(alloy_block_to_block(block)), transaction_receipts: transaction_receipts .into_iter() - .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)) + .map(|receipt| receipt) .collect(), }) } @@ -1903,7 +1902,7 @@ pub(crate) fn parse_log_triggers( .transaction_receipts .iter() .flat_map(move |receipt| { - receipt.logs.iter().enumerate().map(move |(index, _)| { + receipt.logs().iter().enumerate().map(move |(index, _)| { EthereumTrigger::Log(LogRef::LogPosition(index, receipt.cheap_clone())) }) }) @@ -2525,8 +2524,6 @@ async fn get_logs_and_transactions( .transaction_hash .and_then(|txn| transaction_receipts_by_hash.get(&txn).cloned()); let web3_log = alloy_log_to_web3_log(log); - let optional_receipt = optional_receipt - .map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt)); let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(web3_log), optional_receipt)); log_triggers.push(value); } diff --git a/chain/ethereum/src/runtime/abi.rs b/chain/ethereum/src/runtime/abi.rs index 7af6470bf40..d891b346173 100644 --- a/chain/ethereum/src/runtime/abi.rs +++ b/chain/ethereum/src/runtime/abi.rs @@ -2,7 +2,11 @@ use super::runtime_adapter::UnresolvedContractCall; use crate::trigger::{ EthereumBlockData, EthereumCallData, EthereumEventData, EthereumTransactionData, }; +use anyhow::anyhow; use graph::abi; +use graph::prelude::alloy; +use graph::prelude::alloy::network::ReceiptResponse; +use graph::prelude::alloy::primitives::B256; use graph::{ prelude::{ web3::types::{Log, TransactionReceipt, H256}, @@ -82,6 +86,20 @@ impl ToAscObj for Vec { } } +impl ToAscObj for &[alloy::primitives::B256] { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + let topics = self + .iter() + .map(|topic| asc_new(heap, topic, gas)) + .collect::, _>>()?; + Ok(AscTopicArray(Array::new(&topics, heap, gas)?)) + } +} + impl AscIndexId for AscTopicArray { const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayH256; } @@ -101,6 +119,20 @@ impl AscType for AscLogArray { } } +impl ToAscObj for &[alloy::rpc::types::Log] { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + let logs = self + .iter() + .map(|log| asc_new(heap, &log, gas)) + .collect::, _>>()?; + Ok(AscLogArray(Array::new(&logs, heap, gas)?)) + } +} + impl ToAscObj for Vec { fn to_asc_obj( &self, @@ -627,6 +659,50 @@ where } } +impl<'a, T, B> ToAscObj> + for ( + EthereumEventData<'a>, + Option<&alloy::rpc::types::TransactionReceipt>, + ) +where + T: AscType + AscIndexId, + B: AscType + AscIndexId, + EthereumTransactionData<'a>: ToAscObj, + EthereumBlockData<'a>: ToAscObj, +{ + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result, HostExportError> { + let (event_data, optional_receipt) = self; + let AscEthereumEvent { + address, + log_index, + transaction_log_index, + log_type, + block, + transaction, + params, + } = event_data.to_asc_obj(heap, gas)?; + let receipt = if let Some(receipt_data) = optional_receipt { + asc_new(heap, receipt_data, gas)? + } else { + AscPtr::null() + }; + Ok(AscEthereumEvent_0_0_7 { + address, + log_index, + transaction_log_index, + log_type, + block, + transaction, + params, + receipt, + }) + } +} + impl ToAscObj for Log { fn to_asc_obj( &self, @@ -674,6 +750,92 @@ impl ToAscObj for Log { } } +impl ToAscObj for alloy::rpc::types::Log { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + Ok(AscEthereumLog { + address: asc_new(heap, &self.address(), gas)?, + topics: asc_new(heap, &self.topics(), gas)?, + data: asc_new(heap, self.data().data.as_ref(), gas)?, + block_hash: self + .block_hash + .map(|block_hash| asc_new(heap, &block_hash, gas)) + .unwrap_or(Ok(AscPtr::null()))?, + block_number: self + .block_number + .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) + .unwrap_or(Ok(AscPtr::null()))?, + transaction_hash: self + .transaction_hash + .map(|txn_hash| asc_new(heap, &txn_hash, gas)) + .unwrap_or(Ok(AscPtr::null()))?, + transaction_index: self + .transaction_index + .map(|txn_index| asc_new(heap, &BigInt::from(txn_index), gas)) + .unwrap_or(Ok(AscPtr::null()))?, + log_index: self + .log_index + .map(|log_index| asc_new(heap, &BigInt::from(log_index), gas)) + .unwrap_or(Ok(AscPtr::null()))?, + transaction_log_index: AscPtr::null(), // TODO(alloy): figure out how to get transaction log index + log_type: AscPtr::null(), // TODO(alloy): figure out how to get log type + removed: asc_new( + heap, + &AscWrapped { + inner: self.removed, + }, + gas, + )?, + }) + } +} + +impl ToAscObj for &alloy::rpc::types::TransactionReceipt { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + Ok(AscEthereumTransactionReceipt { + transaction_hash: asc_new(heap, &self.transaction_hash, gas)?, + transaction_index: asc_new( + heap, + &BigInt::from( + self.transaction_index + .ok_or(HostExportError::Unknown(anyhow!( + "Transaction index is missing" + )))?, + ), + gas, + )?, + block_hash: self + .block_hash + .map(|block_hash| asc_new(heap, &block_hash, gas)) + .unwrap_or(Ok(AscPtr::null()))?, + block_number: self + .block_number + .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) + .unwrap_or(Ok(AscPtr::null()))?, + cumulative_gas_used: asc_new(heap, &BigInt::from(self.gas_used), gas)?, + gas_used: asc_new(heap, &BigInt::from(self.gas_used), gas)?, + contract_address: self + .contract_address + .map(|contract_address| asc_new(heap, &contract_address, gas)) + .unwrap_or(Ok(AscPtr::null()))?, + logs: asc_new(heap, &self.logs(), gas)?, + status: asc_new(heap, &BigInt::from(self.status() as u64), gas)?, + root: self + .state_root() + .map(|root| asc_new(heap, &root, gas)) + .unwrap_or(Ok(AscPtr::null()))?, + logs_bloom: asc_new(heap, self.inner.logs_bloom().as_slice(), gas)?, + }) + } +} + impl ToAscObj for &TransactionReceipt { fn to_asc_obj( &self, diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index 489f3e2768c..b068d4f766f 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -5,10 +5,11 @@ use graph::data::subgraph::API_VERSION_0_0_2; use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; +use graph::prelude::alloy::rpc::types::TransactionReceipt as AlloyTransactionReceipt; +use graph::prelude::alloy_log_to_web3_log; use graph::prelude::web3::types::Address; use graph::prelude::web3::types::Log; use graph::prelude::web3::types::Transaction; -use graph::prelude::web3::types::TransactionReceipt; use graph::prelude::web3::types::H160; use graph::prelude::web3::types::H256; use graph::prelude::web3::types::U128; @@ -24,6 +25,7 @@ use graph::runtime::AscHeap; use graph::runtime::AscPtr; use graph::runtime::HostExportError; use graph::semver::Version; +use graph::util::conversions::alloy_log_ref_to_web3_log_ref; use graph_runtime_wasm::module::ToAscPtr; use std::{cmp::Ordering, sync::Arc}; @@ -45,7 +47,7 @@ pub enum MappingTrigger { transaction: Arc, log: Arc, params: Vec, - receipt: Option>, + receipt: Option>, calls: Vec, }, Call { @@ -221,19 +223,21 @@ impl ToAscPtr for MappingTrigger { #[derive(Clone, Debug)] pub enum LogRef { - FullLog(Arc, Option>), - LogPosition(usize, Arc), + FullLog(Arc, Option>), + LogPosition(usize, Arc), } impl LogRef { pub fn log(&self) -> &Log { match self { LogRef::FullLog(log, _) => log.as_ref(), - LogRef::LogPosition(index, receipt) => receipt.logs.get(*index).unwrap(), + LogRef::LogPosition(index, receipt) => { + alloy_log_ref_to_web3_log_ref(receipt.logs().get(*index).unwrap()) + } } } - pub fn receipt(&self) -> Option<&Arc> { + pub fn receipt(&self) -> Option<&Arc> { match self { LogRef::FullLog(_, receipt) => receipt.as_ref(), LogRef::LogPosition(_, receipt) => Some(receipt), diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index 19ac22668cc..dea14a373c2 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -7,7 +7,8 @@ use crate::{ alloy_todo, blockchain::{BlockPtr, BlockTime}, prelude::{ - alloy::rpc::types::Block as AlloyBlock, alloy_address_to_h160, b256_to_h256, BlockNumber, + alloy::rpc::types::Block as AlloyBlock, alloy_address_to_h160, b256_to_h256, h256_to_b256, + BlockNumber, }, util::conversions::{alloy_bytes_to_web3_bytes, alloy_u256_to_web3_u256, u64_to_web3_u256}, }; @@ -193,12 +194,12 @@ impl EthereumBlockWithCalls { .ethereum_block .transaction_receipts .iter() - .find(|txn| txn.transaction_hash == call_transaction_hash) + .find(|txn| txn.transaction_hash == h256_to_b256(call_transaction_hash)) .ok_or(anyhow::anyhow!( "failed to find the receipt for this transaction" ))?; - Ok(evaluate_transaction_status(receipt.status)) + Ok(receipt.status()) } } @@ -215,7 +216,7 @@ pub fn evaluate_transaction_status(receipt_status: Option) -> bool { #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct EthereumBlock { pub block: Arc, - pub transaction_receipts: Vec>, + pub transaction_receipts: Vec>, } #[derive(Debug, Default, Clone, PartialEq, Eq)] diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index e385d7eca76..f4cfad0da4b 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -89,6 +89,10 @@ pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { } } +pub fn alloy_log_ref_to_web3_log_ref(log: &AlloyLog) -> &Web3Log { + unimplemented!() +} + #[macro_export] macro_rules! alloy_todo { () => { diff --git a/runtime/wasm/src/to_from/external.rs b/runtime/wasm/src/to_from/external.rs index 6602a17f2b1..b8f0d0e61fa 100644 --- a/runtime/wasm/src/to_from/external.rs +++ b/runtime/wasm/src/to_from/external.rs @@ -71,6 +71,28 @@ impl ToAscObj for alloy::primitives::Address { } } +impl ToAscObj for alloy::primitives::B256 { + fn to_asc_obj( + &self, + heap: &mut H, + gas: &GasCounter, + ) -> Result { + self.as_slice().to_asc_obj(heap, gas) + } +} + +impl FromAscObj for alloy::primitives::B256 { + fn from_asc_obj( + typed_array: Uint8Array, + heap: &H, + gas: &GasCounter, + depth: usize, + ) -> Result { + let data = <[u8; 32]>::from_asc_obj(typed_array, heap, gas, depth)?; + Ok(Self(data)) + } +} + impl FromAscObj for web3::H256 { fn from_asc_obj( typed_array: Uint8Array, From 38c78392285da06e01b10d7e2e7dac3194c9f428 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Thu, 26 Jun 2025 23:39:54 +0530 Subject: [PATCH 38/44] minor refactor --- chain/ethereum/src/data_source.rs | 4 +--- chain/ethereum/src/trigger.rs | 1 - tests/src/fixture/ethereum.rs | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index 8e7fe606f42..bbf93a46b38 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -16,8 +16,6 @@ use graph::env::ENV_VARS; use graph::futures03::future::try_join; use graph::futures03::stream::FuturesOrdered; use graph::futures03::TryStreamExt; -use graph::prelude::web3::types::Address; -use graph::prelude::web3::types::H160; use graph::prelude::{Link, SubgraphManifestValidationError}; use graph::slog::{debug, error, o, trace}; use itertools::Itertools; @@ -34,7 +32,7 @@ use graph::{ blockchain::{self, Blockchain}, prelude::{ async_trait, serde_json, warn, - web3::types::{Log, Transaction, H256}, + web3::types::{Address, Log, Transaction, H160, H256}, BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, LinkResolver, Logger, }, diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index b068d4f766f..46aa34673f4 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -6,7 +6,6 @@ use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; use graph::prelude::alloy::rpc::types::TransactionReceipt as AlloyTransactionReceipt; -use graph::prelude::alloy_log_to_web3_log; use graph::prelude::web3::types::Address; use graph::prelude::web3::types::Log; use graph::prelude::web3::types::Transaction; diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index b8868b3b58f..8acbcbc49b8 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -14,9 +14,8 @@ use graph::cheap_clone::CheapClone; use graph::components::ethereum::BlockWrapper; use graph::data_source::subgraph; use graph::prelude::web3::types::H256; -use graph::prelude::web3::types::U64; use graph::prelude::web3::types::{Address, Log, Transaction, H160}; -use graph::prelude::{tiny_keccak, web3, DeploymentHash, Entity, ENV_VARS}; +use graph::prelude::{tiny_keccak, DeploymentHash, Entity, ENV_VARS}; use graph::schema::EntityType; use graph::{abi, alloy_todo}; use graph_chain_ethereum::network::EthereumNetworkAdapters; From e836a5361107cbca1fcf5a4a04c0cf370f045976 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Fri, 27 Jun 2025 00:07:43 +0530 Subject: [PATCH 39/44] checkpoint --- chain/ethereum/src/data_source.rs | 65 +++++++++++++------------ chain/ethereum/src/trigger.rs | 22 ++++----- graph/src/components/ethereum/types.rs | 67 ++++++-------------------- 3 files changed, 59 insertions(+), 95 deletions(-) diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index bbf93a46b38..83322f2f1f8 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -1,6 +1,5 @@ use anyhow::{anyhow, Error}; use anyhow::{ensure, Context}; -use graph::abi; use graph::abi::EventExt; use graph::abi::FunctionExt; use graph::blockchain::{BlockPtr, TriggerWithHandler}; @@ -16,8 +15,11 @@ use graph::env::ENV_VARS; use graph::futures03::future::try_join; use graph::futures03::stream::FuturesOrdered; use graph::futures03::TryStreamExt; -use graph::prelude::{Link, SubgraphManifestValidationError}; +use graph::prelude::alloy::primitives::{Address, B256}; +use graph::prelude::alloy::rpc::types::Log; +use graph::prelude::{alloy, b256_to_h256, Link, SubgraphManifestValidationError}; use graph::slog::{debug, error, o, trace}; +use graph::{abi, alloy_todo}; use itertools::Itertools; use serde::de::Error as ErrorD; use serde::{Deserialize, Deserializer}; @@ -32,7 +34,7 @@ use graph::{ blockchain::{self, Blockchain}, prelude::{ async_trait, serde_json, warn, - web3::types::{Address, Log, Transaction, H160, H256}, + web3::types::{H160, H256}, BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, LinkResolver, Logger, }, @@ -459,7 +461,7 @@ impl DataSource { }) } - fn handlers_for_log(&self, log: &Log) -> Vec { + fn handlers_for_log(&self, log: &alloy::rpc::types::Log) -> Vec { self.mapping .event_handlers .iter() @@ -637,7 +639,7 @@ impl DataSource { return true; }; - ds_address == *trigger_address + ds_address == trigger_address } /// Checks if `trigger` matches this data source, and if so decodes it into a `MappingTrigger`. @@ -745,17 +747,18 @@ impl DataSource { // See also ca0edc58-0ec5-4c89-a7dd-2241797f5e50. // There is another special case in zkSync-era, where the transaction hash in this case would be zero // See https://docs.zksync.io/zk-stack/concepts/blocks.html#fictive-l2-block-finalizing-the-batch - let transaction = if log.transaction_hash == block.hash_h256() - || log.transaction_hash == Some(H256::zero()) + let transaction = if log.transaction_hash == Some(block.hash()) + || log.transaction_hash == Some(B256::ZERO) { - Transaction { - hash: log.transaction_hash.unwrap(), - block_hash: block.hash_h256(), - block_number: block.number_web3_u64(), - transaction_index: log.transaction_index, - from: Some(H160::zero()), - ..Transaction::default() - } + // Transaction { + // hash: log.transaction_hash.unwrap(), + // block_hash: block.hash_h256(), + // block_number: block.number_web3_u64(), + // transaction_index: log.transaction_index, + // from: Some(H160::zero()), + // ..Transaction::default() + // } + alloy_todo!() } else { // This is the general case where the log's transaction hash does not match the block's hash // and is not a special zero hash, implying a real transaction associated with this log. @@ -1405,12 +1408,12 @@ pub struct MappingCallHandler { #[derive(Clone, Debug, Hash, Eq, PartialEq, Deserialize)] pub struct MappingEventHandler { pub event: String, - pub topic0: Option, - #[serde(deserialize_with = "deserialize_h256_vec", default)] - pub topic1: Option>, - #[serde(deserialize_with = "deserialize_h256_vec", default)] - pub topic2: Option>, - #[serde(deserialize_with = "deserialize_h256_vec", default)] + pub topic0: Option, + #[serde(deserialize_with = "deserialize_b256_vec", default)] + pub topic1: Option>, + #[serde(deserialize_with = "deserialize_b256_vec", default)] + pub topic2: Option>, + #[serde(deserialize_with = "deserialize_b256_vec", default)] pub topic3: Option>, pub handler: String, #[serde(default)] @@ -1420,7 +1423,7 @@ pub struct MappingEventHandler { } // Custom deserializer for H256 fields that removes the '0x' prefix before parsing -fn deserialize_h256_vec<'de, D>(deserializer: D) -> Result>, D::Error> +fn deserialize_b256_vec<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { @@ -1428,19 +1431,19 @@ where match s { Some(vec) => { - let mut h256_vec = Vec::new(); + let mut b256_vec = Vec::new(); for hex_str in vec { // Remove '0x' prefix if present let clean_hex_str = hex_str.trim_start_matches("0x"); // Ensure the hex string is 64 characters long, after removing '0x' let padded_hex_str = format!("{:0>64}", clean_hex_str); // Parse the padded string into H256, handling potential errors - h256_vec.push( - H256::from_str(&padded_hex_str) - .map_err(|e| D::Error::custom(format!("Failed to parse H256: {}", e)))?, + b256_vec.push( + B256::from_str(&padded_hex_str) + .map_err(|e| D::Error::custom(format!("Failed to parse B256: {}", e)))?, ); } - Ok(Some(h256_vec)) + Ok(Some(b256_vec)) } None => Ok(None), } @@ -1453,16 +1456,16 @@ impl MappingEventHandler { } pub fn matches(&self, log: &Log) -> bool { - let matches_topic = |index: usize, topic_opt: &Option>| -> bool { + let matches_topic = |index: usize, topic_opt: &Option>| -> bool { topic_opt.as_ref().map_or(true, |topic_vec| { - log.topics + log.topics() .get(index) .map_or(false, |log_topic| topic_vec.contains(log_topic)) }) }; - if let Some(topic0) = log.topics.get(0) { - return self.topic0() == *topic0 + if let Some(topic0) = log.topics().get(0) { + return self.topic0() == b256_to_h256(*topic0) && matches_topic(1, &self.topic1) && matches_topic(2, &self.topic2) && matches_topic(3, &self.topic3); diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index 46aa34673f4..8cac5cc443d 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -5,9 +5,10 @@ use graph::data::subgraph::API_VERSION_0_0_2; use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; +use graph::prelude::alloy::primitives::Address; +use graph::prelude::alloy::primitives::B256; +use graph::prelude::alloy::rpc::types::Log; use graph::prelude::alloy::rpc::types::TransactionReceipt as AlloyTransactionReceipt; -use graph::prelude::web3::types::Address; -use graph::prelude::web3::types::Log; use graph::prelude::web3::types::Transaction; use graph::prelude::web3::types::H160; use graph::prelude::web3::types::H256; @@ -24,7 +25,6 @@ use graph::runtime::AscHeap; use graph::runtime::AscPtr; use graph::runtime::HostExportError; use graph::semver::Version; -use graph::util::conversions::alloy_log_ref_to_web3_log_ref; use graph_runtime_wasm::module::ToAscPtr; use std::{cmp::Ordering, sync::Arc}; @@ -230,9 +230,7 @@ impl LogRef { pub fn log(&self) -> &Log { match self { LogRef::FullLog(log, _) => log.as_ref(), - LogRef::LogPosition(index, receipt) => { - alloy_log_ref_to_web3_log_ref(receipt.logs().get(*index).unwrap()) - } + LogRef::LogPosition(index, receipt) => receipt.logs().get(*index).unwrap(), } } @@ -243,27 +241,27 @@ impl LogRef { } } - pub fn log_index(&self) -> Option { + pub fn log_index(&self) -> Option { self.log().log_index } - pub fn transaction_index(&self) -> Option { + pub fn transaction_index(&self) -> Option { self.log().transaction_index } - fn transaction_hash(&self) -> Option { + fn transaction_hash(&self) -> Option { self.log().transaction_hash } - pub fn block_hash(&self) -> Option { + pub fn block_hash(&self) -> Option { self.log().block_hash } - pub fn block_number(&self) -> Option { + pub fn block_number(&self) -> Option { self.log().block_number } - pub fn address(&self) -> &H160 { + pub fn address(&self) -> &Address { &self.log().address } } diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index dea14a373c2..8dbfcdae856 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -1,7 +1,10 @@ -use alloy::rpc::types::trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}; +use alloy::{ + primitives::B256, + rpc::types::trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}, +}; use serde::{Deserialize, Serialize}; -use std::{convert::TryFrom, sync::Arc}; -use web3::types::{Address, Bytes, Log, Transaction, TransactionReceipt, H256, U256, U64}; +use std::sync::Arc; +use web3::types::{Address, Bytes, Log, Transaction, U256, U64}; use crate::{ alloy_todo, @@ -22,11 +25,15 @@ impl BlockWrapper { Self(block) } - pub fn hash_h256(&self) -> Option { + pub fn hash_h256(&self) -> Option { alloy_todo!() // self.0.hash } + pub fn hash(&self) -> B256 { + self.0.header.hash + } + pub fn number_u64(&self) -> Option { alloy_todo!() // self.0.number.map(|n| n.as_u64()) @@ -57,7 +64,7 @@ pub type LightEthereumBlock = BlockWrapper; pub trait LightEthereumBlockExt { fn number(&self) -> BlockNumber; - fn transaction_for_log(&self, log: &Log) -> Option; + fn transaction_for_log(&self, log: &alloy::rpc::types::Log) -> Option; fn transaction_for_call(&self, call: &EthereumCall) -> Option; fn parent_ptr(&self) -> Option; fn format(&self) -> String; @@ -106,7 +113,7 @@ impl LightEthereumBlockExt for LightEthereumBlock { self.0.number() } - fn transaction_for_log(&self, log: &Log) -> Option { + fn transaction_for_log(&self, log: &alloy::rpc::types::Log) -> Option { self.0.transaction_for_log(log) } @@ -131,50 +138,6 @@ impl LightEthereumBlockExt for LightEthereumBlock { } } -impl LightEthereumBlockExt for web3::types::Block { - fn number(&self) -> BlockNumber { - BlockNumber::try_from(self.number.unwrap().as_u64()).unwrap() - } - - fn transaction_for_log(&self, log: &Log) -> Option { - log.transaction_hash - .and_then(|hash| self.transactions.iter().find(|tx| tx.hash == hash)) - .cloned() - } - - fn transaction_for_call(&self, call: &EthereumCall) -> Option { - call.transaction_hash - .and_then(|hash| self.transactions.iter().find(|tx| tx.hash == hash)) - .cloned() - } - - fn parent_ptr(&self) -> Option { - match self.number() { - 0 => None, - n => Some(BlockPtr::from((self.parent_hash, n - 1))), - } - } - - fn format(&self) -> String { - format!( - "{} ({})", - self.number - .map_or(String::from("none"), |number| format!("#{}", number)), - self.hash - .map_or(String::from("-"), |hash| format!("{:x}", hash)) - ) - } - - fn block_ptr(&self) -> BlockPtr { - BlockPtr::from((self.hash.unwrap(), self.number.unwrap().as_u64())) - } - - fn timestamp(&self) -> BlockTime { - let ts = i64::try_from(self.timestamp.as_u64()).unwrap(); - BlockTime::since_epoch(ts, 0) - } -} - #[derive(Clone, Debug)] pub struct EthereumBlockWithCalls { pub ethereum_block: EthereumBlock, @@ -228,8 +191,8 @@ pub struct EthereumCall { pub input: Bytes, pub output: Bytes, pub block_number: BlockNumber, - pub block_hash: H256, - pub transaction_hash: Option, + pub block_hash: B256, + pub transaction_hash: Option, pub transaction_index: u64, } From 30012e297a087d66752da307838170c4078f2142 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Sun, 29 Jun 2025 13:29:55 +0530 Subject: [PATCH 40/44] migrate web3 primitives to alloy_primitives --- Cargo.lock | 52 +++ Cargo.toml | 2 +- chain/ethereum/src/adapter.rs | 281 ++++-------- chain/ethereum/src/codec.rs | 248 ++++++----- chain/ethereum/src/data_source.rs | 38 +- chain/ethereum/src/ethereum_adapter.rs | 69 ++- chain/ethereum/src/runtime/abi.rs | 409 +++++++++--------- chain/ethereum/src/runtime/runtime_adapter.rs | 6 +- chain/ethereum/src/tests.rs | 107 +++-- chain/ethereum/src/trigger.rs | 145 +++---- chain/near/src/codec.rs | 13 +- chain/near/src/trigger.rs | 8 +- graph/src/abi/event_ext.rs | 51 +-- graph/src/abi/mod.rs | 2 +- graph/src/blockchain/mock.rs | 8 +- graph/src/blockchain/types.rs | 175 +++----- graph/src/components/ethereum/types.rs | 55 ++- graph/src/components/store/mod.rs | 3 +- graph/src/components/store/traits.rs | 10 +- .../subgraph/proof_of_indexing/mod.rs | 12 +- .../subgraph/proof_of_indexing/online.rs | 4 +- .../subgraph/proof_of_indexing/reference.rs | 13 +- graph/src/components/transaction_receipt.rs | 54 +-- graph/src/data/graphql/values.rs | 13 +- graph/src/data/store/ethereum.rs | 16 +- graph/src/data/store/scalar/bigint.rs | 34 +- graph/src/data/subgraph/mod.rs | 2 +- graph/src/data_source/common.rs | 43 +- graph/src/lib.rs | 4 +- graph/src/runtime/mod.rs | 2 +- graphql/src/store/resolver.rs | 7 +- node/src/manager/commands/check_blocks.rs | 33 +- runtime/test/src/common.rs | 2 +- runtime/test/src/test.rs | 9 +- runtime/test/src/test/abi.rs | 15 +- runtime/wasm/src/host_exports.rs | 20 +- runtime/wasm/src/module/context.rs | 2 +- runtime/wasm/src/to_from/external.rs | 54 +-- server/index-node/src/resolver.rs | 4 +- store/postgres/src/chain_store.rs | 55 ++- store/postgres/src/deployment.rs | 10 +- store/postgres/src/deployment_store.rs | 4 +- store/postgres/src/detail.rs | 5 +- store/postgres/src/store.rs | 4 +- store/postgres/src/subgraph_store.rs | 12 +- store/postgres/src/transaction_receipt.rs | 27 +- store/test-store/src/block_store.rs | 9 +- store/test-store/src/store.rs | 11 +- .../tests/chain/ethereum/manifest.rs | 12 +- store/test-store/tests/graph/entity_cache.rs | 4 +- store/test-store/tests/postgres/chain_head.rs | 6 +- store/test-store/tests/postgres/relational.rs | 11 +- .../tests/postgres/relational_bytes.rs | 13 +- store/test-store/tests/postgres/store.rs | 18 +- store/test-store/tests/postgres/writable.rs | 4 +- tests/src/fixture/ethereum.rs | 111 ++--- tests/src/fixture/mod.rs | 5 +- tests/tests/integration_tests.rs | 27 +- tests/tests/runner_tests.rs | 9 +- 59 files changed, 1112 insertions(+), 1270 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5a15372cbc..57153385fd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-trie", + "arbitrary", "auto_impl", "c-kzg", "derive_more 2.0.1", @@ -113,6 +114,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", + "arbitrary", "serde", ] @@ -161,7 +163,10 @@ dependencies = [ "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", + "arbitrary", + "derive_arbitrary", "itoa", + "proptest", "serde", "serde_json", "winnow", @@ -175,7 +180,9 @@ checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ "alloy-primitives", "alloy-rlp", + "arbitrary", "crc", + "rand 0.8.5", "serde", "thiserror 2.0.12", ] @@ -188,6 +195,8 @@ checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" dependencies = [ "alloy-primitives", "alloy-rlp", + "arbitrary", + "rand 0.8.5", "serde", ] @@ -199,7 +208,9 @@ checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" dependencies = [ "alloy-primitives", "alloy-rlp", + "arbitrary", "k256", + "rand 0.8.5", "serde", "thiserror 2.0.12", ] @@ -216,6 +227,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", + "arbitrary", "auto_impl", "c-kzg", "derive_more 2.0.1", @@ -309,9 +321,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a326d47106039f38b811057215a92139f46eef7983a4b77b10930a0ea5685b1e" dependencies = [ "alloy-rlp", + "arbitrary", "bytes", "cfg-if 1.0.1", "const-hex", + "derive_arbitrary", "derive_more 2.0.1", "foldhash", "hashbrown 0.15.4", @@ -321,6 +335,7 @@ dependencies = [ "keccak-asm", "paste", "proptest", + "proptest-derive", "rand 0.9.1", "ruint", "rustc-hash 2.1.1", @@ -506,6 +521,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", + "arbitrary", "derive_more 2.0.1", "rand 0.8.5", "serde", @@ -526,6 +542,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", + "arbitrary", "itertools 0.14.0", "serde", "serde_json", @@ -565,6 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05ace2ef3da874544c3ffacfd73261cdb1405d8631765deb991436a53ec6069" dependencies = [ "alloy-primitives", + "arbitrary", "serde", "serde_json", ] @@ -757,9 +775,13 @@ checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" dependencies = [ "alloy-primitives", "alloy-rlp", + "arbitrary", "arrayvec 0.7.6", + "derive_arbitrary", "derive_more 2.0.1", "nybbles", + "proptest", + "proptest-derive", "serde", "smallvec", "tracing", @@ -841,6 +863,9 @@ name = "arbitrary" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "arc-swap" @@ -1579,6 +1604,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" dependencies = [ + "arbitrary", "blst", "cc", "glob", @@ -2257,6 +2283,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -4086,6 +4123,7 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ + "arbitrary", "equivalent", "hashbrown 0.15.4", "serde", @@ -4736,6 +4774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" dependencies = [ "alloy-rlp", + "arbitrary", "const-hex", "proptest", "serde", @@ -5338,6 +5377,17 @@ dependencies = [ "unarray", ] +[[package]] +name = "proptest-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "prost" version = "0.13.5" @@ -5841,6 +5891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" dependencies = [ "alloy-rlp", + "arbitrary", "ark-ff 0.3.0", "ark-ff 0.4.2", "bytes", @@ -6491,6 +6542,7 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ + "arbitrary", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index ab953c993a1..90d5266328a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ repository = "https://github.com/graphprotocol/graph-node" license = "MIT OR Apache-2.0" [workspace.dependencies] -alloy = { version = "0.15.10", features = ["full"] } +alloy = { version = "0.15.10", features = ["full", "arbitrary"] } alloy-rpc-types = "0.15.10" anyhow = "1.0" async-graphql = { version = "7.0.15", features = ["chrono"] } diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index ccb787da60d..dcee5ebd58d 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -7,10 +7,11 @@ use graph::data_source::common::ContractCall; use graph::firehose::CallToFilter; use graph::firehose::CombinedFilter; use graph::firehose::LogFilter; +use graph::prelude::alloy::primitives::Address; use graph::prelude::alloy::primitives::B256; use graph::prelude::alloy::rpc::types::Block as AlloyBlock; +use graph::prelude::alloy::rpc::types::Log; use graph::prelude::alloy::transports::{RpcError, TransportErrorKind}; -use graph::prelude::web3::types::H160; use itertools::Itertools; use prost::Message; use prost_types::Any; @@ -19,10 +20,8 @@ use std::collections::{HashMap, HashSet}; use std::fmt; use thiserror::Error; use tiny_keccak::keccak256; -use web3::types::{Address, Log, H256}; use graph::prelude::*; -use graph::prelude::{alloy_address_to_h160, b256_to_h256}; use graph::{ blockchain as bc, components::metrics::{CounterVec, GaugeVec, HistogramVec}, @@ -38,7 +37,7 @@ use crate::capabilities::NodeCapabilities; use crate::data_source::{BlockHandlerFilter, DataSource}; use crate::{Chain, Mapping, ENV_VARS}; -pub type EventSignature = H256; +pub type EventSignature = B256; pub type FunctionSelector = [u8; 4]; /// `EventSignatureWithTopics` is used to match events with @@ -47,19 +46,20 @@ pub type FunctionSelector = [u8; 4]; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct EventSignatureWithTopics { pub address: Option
, - pub signature: H256, - pub topic1: Option>, - pub topic2: Option>, - pub topic3: Option>, + pub signature: B256, + pub topic1: Option>, + pub topic2: Option>, + pub topic3: Option>, } impl EventSignatureWithTopics { + #[allow(dead_code)] pub fn new( address: Option
, - signature: H256, - topic1: Option>, - topic2: Option>, - topic3: Option>, + signature: B256, + topic1: Option>, + topic2: Option>, + topic3: Option>, ) -> Self { EventSignatureWithTopics { address, @@ -70,72 +70,12 @@ impl EventSignatureWithTopics { } } - /// Checks if an event matches the `EventSignatureWithTopics` - /// If self.address is None, it's considered a wildcard match. - /// Otherwise, it must match the provided address. - /// It must also match the topics if they are Some - pub fn matches(&self, address: Option<&H160>, sig: H256, topics: &Vec) -> bool { - // If self.address is None, it's considered a wildcard match. Otherwise, it must match the provided address. - let address_matches = match self.address { - Some(ref self_addr) => address == Some(self_addr), - None => true, // self.address is None, so it matches any address. - }; - - address_matches - && self.signature == sig - && self.topic1.as_ref().map_or(true, |t1| { - topics.get(1).map_or(false, |topic| t1.contains(topic)) - }) - && self.topic2.as_ref().map_or(true, |t2| { - topics.get(2).map_or(false, |topic| t2.contains(topic)) - }) - && self.topic3.as_ref().map_or(true, |t3| { - topics.get(3).map_or(false, |topic| t3.contains(topic)) - }) - } -} - -/// `EventSignatureWithTopics` is used to match events with -/// indexed arguments when they are defined in the subgraph -/// manifest. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct EventSignatureWithTopicsForAlloy { - pub address: Option, - pub signature: alloy::primitives::B256, - pub topic1: Option>, - pub topic2: Option>, - pub topic3: Option>, -} - -impl EventSignatureWithTopicsForAlloy { - #[allow(dead_code)] - pub fn new( - address: Option, - signature: alloy::primitives::B256, - topic1: Option>, - topic2: Option>, - topic3: Option>, - ) -> Self { - EventSignatureWithTopicsForAlloy { - address, - signature, - topic1, - topic2, - topic3, - } - } - /// Checks if an event matches the `EventSignatureWithTopics` /// If self.address is None, it's considered a wildcard match. /// Otherwise, it must match the provided address. /// It must also match the topics if they are Some #[allow(dead_code)] - pub fn matches( - &self, - address: Option<&alloy::primitives::Address>, - sig: alloy::primitives::B256, - topics: &Vec, - ) -> bool { + pub fn matches(&self, address: Option<&Address>, sig: B256, topics: &[B256]) -> bool { // If self.address is None, it's considered a wildcard match. Otherwise, it must match the provided address. let address_matches = match self.address { Some(ref self_addr) => address == Some(self_addr), @@ -158,8 +98,6 @@ impl EventSignatureWithTopicsForAlloy { #[derive(Error, Debug)] pub enum EthereumRpcError { - #[error("call error: {0}")] - Web3Error(web3::Error), #[error("call error: {0}")] AlloyError(RpcError), #[error("ethereum node took too long to perform call")] @@ -175,8 +113,6 @@ pub enum ContractCallError { #[error("error encoding input call data: {0:#}")] EncodingError(anyhow::Error), #[error("call error: {0}")] - Web3Error(web3::Error), - #[error("call error: {0}")] AlloyError(RpcError), #[error("ethereum node took too long to perform call")] Timeout, @@ -190,7 +126,7 @@ impl From for MappingError { // Any error reported by the Ethereum node could be due to the block no longer being on // the main chain. This is very unespecific but we don't want to risk failing a // subgraph due to a transient error such as a reorg. - ContractCallError::Web3Error(e) => MappingError::PossibleReorg(anyhow::anyhow!( + ContractCallError::AlloyError(e) => MappingError::PossibleReorg(anyhow::anyhow!( "Ethereum node returned an error for an eth_call: {e}" )), // Also retry on timeouts. @@ -260,7 +196,7 @@ impl EthGetLogsFilter { } } - fn from_event_with_topics(event: EventSignatureWithTopicsForAlloy) -> Self { + fn from_event_with_topics(event: EventSignatureWithTopics) -> Self { EthGetLogsFilter { contracts: event.address.map_or(vec![], |a| vec![a]), event_signatures: vec![event.signature], @@ -452,14 +388,14 @@ impl EthereumLogFilter { /// Check if this filter matches the specified `Log`. pub fn matches(&self, log: &Log) -> bool { // First topic should be event sig - match log.topics.first() { + match log.topics().first() { None => false, Some(sig) => { // The `Log` matches the filter either if the filter contains // a (contract address, event signature) pair that matches the // `Log`, or if the filter contains wildcard event that matches. - let contract = LogFilterNode::Contract(log.address); + let contract = LogFilterNode::Contract(log.address()); let event = LogFilterNode::Event(*sig); self.contracts_and_events_graph .all_edges() @@ -468,7 +404,7 @@ impl EthereumLogFilter { || self .events_with_topic_filters .iter() - .any(|(e, _)| e.matches(Some(&log.address), *sig, &log.topics)) + .any(|(e, _)| e.matches(Some(&log.address()), *sig, &log.topics())) } } } @@ -476,9 +412,9 @@ impl EthereumLogFilter { /// Similar to [`matches`], checks if a transaction receipt is required for this log filter. pub fn requires_transaction_receipt( &self, - event_signature: &H256, + event_signature: &B256, contract_address: Option<&Address>, - topics: &Vec, + topics: &[B256], ) -> bool { // Check for wildcard events first. if self.wildcard_events.get(event_signature) == Some(&true) { @@ -524,7 +460,7 @@ impl EthereumLogFilter { topics: &[alloy::primitives::B256], ) -> bool { // Check for wildcard events first. - if self.wildcard_events.get(&b256_to_h256(*event_signature)) == Some(&true) { + if self.wildcard_events.get(event_signature) == Some(&true) { return true; } @@ -534,13 +470,7 @@ impl EthereumLogFilter { .iter() .any(|(event_with_topics, &requires_receipt)| { requires_receipt - && event_with_topics.matches( - contract_address - .map(|addr| alloy_address_to_h160(*addr)) - .as_ref(), - b256_to_h256(*event_signature), - &topics.iter().map(|t| b256_to_h256(*t)).collect(), - ) + && event_with_topics.matches(contract_address, *event_signature, topics) }) { return true; @@ -548,8 +478,8 @@ impl EthereumLogFilter { // Finally, check the contracts_and_events_graph if a contract address is specified. if let Some(address) = contract_address { - let contract_node = LogFilterNode::Contract(alloy_address_to_h160(*address)); - let event_node = LogFilterNode::Event(b256_to_h256(*event_signature)); + let contract_node = LogFilterNode::Contract(*address); + let event_node = LogFilterNode::Event(*event_signature); // Directly iterate over all edges and return true if a matching edge that requires a receipt is found. for (s, t, &r) in self.contracts_and_events_graph.all_edges() { @@ -664,33 +594,18 @@ impl EthereumLogFilter { let mut filters = Vec::new(); // Start with the wildcard event filters. - filters.extend(self.wildcard_events.into_keys().map(|h256_event| { - let alloy_event = alloy::primitives::B256::from_slice(h256_event.as_bytes()); - EthGetLogsFilter::from_event(alloy_event) - })); + filters.extend( + self.wildcard_events + .into_keys() + .map(|event| EthGetLogsFilter::from_event(event)), + ); // Handle events with topic filters. filters.extend( self.events_with_topic_filters .into_iter() .map(|(event_with_topics, _)| { - // Convert EventSignatureWithTopics to EventSignatureWithTopicsForAlloy - let alloy_event = EventSignatureWithTopicsForAlloy { - address: event_with_topics - .address - .map(|addr| h160_to_alloy_address(addr)), - signature: h256_to_b256(event_with_topics.signature), - topic1: event_with_topics - .topic1 - .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), - topic2: event_with_topics - .topic2 - .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), - topic3: event_with_topics - .topic3 - .map(|topics| topics.into_iter().map(|t| h256_to_b256(t)).collect()), - }; - EthGetLogsFilter::from_event_with_topics(alloy_event) + EthGetLogsFilter::from_event_with_topics(event_with_topics) }), ); @@ -721,14 +636,8 @@ impl EthereumLogFilter { // If there are edges, there are vertexes. let max_vertex = g.nodes().max_by_key(|&n| g.neighbors(n).count()).unwrap(); let mut filter = match max_vertex { - LogFilterNode::Contract(address) => { - let alloy_address = alloy::primitives::Address::from_slice(address.as_bytes()); - EthGetLogsFilter::from_contract(alloy_address) - } - LogFilterNode::Event(event_sig) => { - let alloy_event = alloy::primitives::B256::from_slice(event_sig.as_bytes()); - EthGetLogsFilter::from_event(alloy_event) - } + LogFilterNode::Contract(address) => EthGetLogsFilter::from_contract(address), + LogFilterNode::Event(event_sig) => EthGetLogsFilter::from_event(event_sig), }; for neighbor in g.neighbors(max_vertex) { match neighbor { @@ -739,13 +648,10 @@ impl EthereumLogFilter { push_filter(filter); filter = EthGetLogsFilter::from_event(event); } - let alloy_address = - alloy::primitives::Address::from_slice(address.as_bytes()); - filter.contracts.push(alloy_address); + filter.contracts.push(address); } LogFilterNode::Event(event_sig) => { - let alloy_event = alloy::primitives::B256::from_slice(event_sig.as_bytes()); - filter.event_signatures.push(alloy_event); + filter.event_signatures.push(event_sig); } } } @@ -791,7 +697,7 @@ impl Into> for EthereumCallFilter { let mut filters: Vec = contract_addresses_function_signatures .into_iter() .map(|(addr, (_, sigs))| CallToFilter { - addresses: vec![addr.to_fixed_bytes().to_vec()], + addresses: vec![addr.to_vec()], signatures: sigs.into_iter().map(|x| x.to_vec()).collect_vec(), }) .collect(); @@ -981,7 +887,7 @@ impl Into> for EthereumBlockFilter { .sorted() .dedup_by(|x, y| x == y) .map(|addr| CallToFilter { - addresses: vec![addr.to_fixed_bytes().to_vec()], + addresses: vec![addr.to_vec()], signatures: vec![], }) .collect_vec() @@ -1333,9 +1239,7 @@ mod tests { use graph::blockchain::TriggerFilter as _; use graph::firehose::{CallToFilter, CombinedFilter, LogFilter, MultiLogFilter}; use graph::petgraph::graphmap::GraphMap; - use graph::prelude::web3::types::Address; - use graph::prelude::web3::types::Bytes; - use graph::prelude::web3::types::H256; + use graph::prelude::alloy::primitives::{Address, Bytes, B256}; use graph::prelude::EthereumCall; use hex::ToHex; use itertools::Itertools; @@ -1362,7 +1266,7 @@ mod tests { .map(|addr| { format!( "0x{}", - H256::from_str(addr) + B256::from_str(addr) .expect("unable to parse addr") .encode_hex::() ) @@ -1373,16 +1277,11 @@ mod tests { let sigs = event_sigs .iter() - .map(|addr| { - H256::from_str(addr) - .expect("unable to parse addr") - .to_fixed_bytes() - .to_vec() - }) + .map(|addr| B256::from_str(addr).expect("unable to parse addr").to_vec()) .collect_vec(); let filter = LogFilter { - addresses: vec![address.to_fixed_bytes().to_vec()], + addresses: vec![address.to_vec()], event_signatures: sigs, }; // This base64 was provided by Streamingfast as a binding example of the expected encoded for the @@ -1411,7 +1310,6 @@ mod tests { let filter = LogFilter { addresses: vec![Address::from_str(hex_addr) .expect("failed to parse address") - .to_fixed_bytes() .to_vec()], event_signatures: vec![fs.to_vec()], }; @@ -1426,8 +1324,8 @@ mod tests { #[test] fn ethereum_trigger_filter_to_firehose() { - let address = Address::from_low_u64_be; - let sig = H256::from_low_u64_le; + let address = |value: u64| Address::from_slice(&value.to_le_bytes()); + let sig = |value: u64| B256::from_slice(&value.to_le_bytes()); let mut filter = TriggerFilter { log: EthereumLogFilter { contracts_and_events_graph: GraphMap::new(), @@ -1457,27 +1355,27 @@ mod tests { let expected_call_filters = vec![ CallToFilter { - addresses: vec![address(0).to_fixed_bytes().to_vec()], + addresses: vec![address(0).to_vec()], signatures: vec![[0u8; 4].to_vec()], }, CallToFilter { - addresses: vec![address(1).to_fixed_bytes().to_vec()], + addresses: vec![address(1).to_vec()], signatures: vec![[1u8; 4].to_vec()], }, CallToFilter { - addresses: vec![address(2).to_fixed_bytes().to_vec()], + addresses: vec![address(2).to_vec()], signatures: vec![], }, CallToFilter { - addresses: vec![address(1000).to_fixed_bytes().to_vec()], + addresses: vec![address(1000).to_vec()], signatures: vec![], }, CallToFilter { - addresses: vec![address(2000).to_fixed_bytes().to_vec()], + addresses: vec![address(2000).to_vec()], signatures: vec![], }, CallToFilter { - addresses: vec![address(3000).to_fixed_bytes().to_vec()], + addresses: vec![address(3000).to_vec()], signatures: vec![], }, ]; @@ -1500,15 +1398,12 @@ mod tests { let expected_log_filters = vec![ LogFilter { - addresses: vec![address(10).to_fixed_bytes().to_vec()], - event_signatures: vec![sig(101).to_fixed_bytes().to_vec()], + addresses: vec![address(10).to_vec()], + event_signatures: vec![sig(101).to_vec()], }, LogFilter { - addresses: vec![ - address(10).to_fixed_bytes().to_vec(), - address(20).to_fixed_bytes().to_vec(), - ], - event_signatures: vec![sig(100).to_fixed_bytes().to_vec()], + addresses: vec![address(10).to_vec(), address(20).to_vec()], + event_signatures: vec![sig(100).to_vec()], }, ]; @@ -1552,8 +1447,8 @@ mod tests { #[test] fn ethereum_trigger_filter_to_firehose_every_block_plus_logfilter() { - let address = Address::from_low_u64_be; - let sig = H256::from_low_u64_le; + let address = |value: u64| Address::from_slice(&value.to_le_bytes()); + let sig = |value: u64| B256::from_slice(&value.to_le_bytes()); let mut filter = TriggerFilter { log: EthereumLogFilter { contracts_and_events_graph: GraphMap::new(), @@ -1578,8 +1473,8 @@ mod tests { ); let expected_log_filters = vec![LogFilter { - addresses: vec![address(10).to_fixed_bytes().to_vec()], - event_signatures: vec![sig(101).to_fixed_bytes().to_vec()], + addresses: vec![address(10).to_vec()], + event_signatures: vec![sig(101).to_vec()], }]; let firehose_filter = filter.clone().to_firehose_filter(); @@ -1869,51 +1764,36 @@ mod tests { fn extending_ethereum_call_filter() { let mut base = EthereumCallFilter { contract_addresses_function_signatures: HashMap::from_iter(vec![ - ( - Address::from_low_u64_be(0), - (0, HashSet::from_iter(vec![[0u8; 4]])), - ), - ( - Address::from_low_u64_be(1), - (1, HashSet::from_iter(vec![[1u8; 4]])), - ), + (address(0), (0, HashSet::from_iter(vec![[0u8; 4]]))), + (address(1), (1, HashSet::from_iter(vec![[1u8; 4]]))), ]), wildcard_signatures: HashSet::new(), }; let extension = EthereumCallFilter { contract_addresses_function_signatures: HashMap::from_iter(vec![ - ( - Address::from_low_u64_be(0), - (2, HashSet::from_iter(vec![[2u8; 4]])), - ), - ( - Address::from_low_u64_be(3), - (3, HashSet::from_iter(vec![[3u8; 4]])), - ), + (address(0), (2, HashSet::from_iter(vec![[2u8; 4]]))), + (address(3), (3, HashSet::from_iter(vec![[3u8; 4]]))), ]), wildcard_signatures: HashSet::new(), }; base.extend(extension); assert_eq!( - base.contract_addresses_function_signatures - .get(&Address::from_low_u64_be(0)), + base.contract_addresses_function_signatures.get(&address(0)), Some(&(0, HashSet::from_iter(vec![[0u8; 4], [2u8; 4]]))) ); assert_eq!( - base.contract_addresses_function_signatures - .get(&Address::from_low_u64_be(3)), + base.contract_addresses_function_signatures.get(&address(3)), Some(&(3, HashSet::from_iter(vec![[3u8; 4]]))) ); assert_eq!( - base.contract_addresses_function_signatures - .get(&Address::from_low_u64_be(1)), + base.contract_addresses_function_signatures.get(&address(1)), Some(&(1, HashSet::from_iter(vec![[1u8; 4]]))) ); } - fn address(id: u64) -> Address { - Address::from_low_u64_be(id) + fn address(value: u64) -> Address { + Address::from_slice(&value.to_le_bytes()) } fn bytes(value: Vec) -> Bytes { @@ -1943,8 +1823,8 @@ fn complete_log_filter() { for &contract in &contracts { for &event in &events { contracts_and_events_graph.add_edge( - LogFilterNode::Contract(alloy_address_to_h160(contract)), - LogFilterNode::Event(b256_to_h256(event)), + LogFilterNode::Contract(contract), + LogFilterNode::Event(event), false, ); } @@ -1987,16 +1867,19 @@ fn complete_log_filter() { #[test] fn log_filter_require_transacion_receipt_method() { + let address = |value: u64| Address::from_slice(&value.to_le_bytes()); + let b256 = |value: u64| B256::from_slice(&value.to_le_bytes()); + // test data - let event_signature_a = H256::zero(); - let event_signature_b = H256::from_low_u64_be(1); - let event_signature_c = H256::from_low_u64_be(2); - let contract_a = Address::from_low_u64_be(3); - let contract_b = Address::from_low_u64_be(4); - let contract_c = Address::from_low_u64_be(5); - - let wildcard_event_with_receipt = H256::from_low_u64_be(6); - let wildcard_event_without_receipt = H256::from_low_u64_be(7); + let event_signature_a = b256(0); + let event_signature_b = b256(1); + let event_signature_c = b256(2); + let contract_a = address(3); + let contract_b = address(4); + let contract_c = address(5); + + let wildcard_event_with_receipt = b256(6); + let wildcard_event_without_receipt = b256(7); let wildcard_events = [ (wildcard_event_with_receipt, true), (wildcard_event_without_receipt, false), @@ -2006,8 +1889,8 @@ fn log_filter_require_transacion_receipt_method() { let events_with_topic_filters = HashMap::new(); // TODO(krishna): Test events with topic filters - let alien_event_signature = H256::from_low_u64_be(8); // those will not be inserted in the graph - let alien_contract_address = Address::from_low_u64_be(9); + let alien_event_signature = b256(8); // those will not be inserted in the graph + let alien_contract_address = address(9); // test graph nodes let event_a_node = LogFilterNode::Event(event_signature_a); @@ -2052,7 +1935,7 @@ fn log_filter_require_transacion_receipt_method() { events_with_topic_filters, }; - let empty_vec: Vec = vec![]; + let empty_vec: Vec = vec![]; // connected contracts and events graph assert!(filter.requires_transaction_receipt(&event_signature_a, Some(&contract_a), &empty_vec)); diff --git a/chain/ethereum/src/codec.rs b/chain/ethereum/src/codec.rs index 45fcb8de57c..bf1e7d85c28 100644 --- a/chain/ethereum/src/codec.rs +++ b/chain/ethereum/src/codec.rs @@ -9,9 +9,9 @@ use graph::{ self, Block as BlockchainBlock, BlockPtr, BlockTime, ChainStoreBlock, ChainStoreData, }, prelude::{ - web3::{ + alloy::{ self, - types::{Bytes, H160, H2048, H256, U256, U64}, + primitives::{aliases::B2048, Address, Bytes, B256}, }, BlockNumber, Error, EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, @@ -37,16 +37,26 @@ where } } -impl TryDecodeProto<[u8; 256], H2048> for &[u8] {} -impl TryDecodeProto<[u8; 32], H256> for &[u8] {} -impl TryDecodeProto<[u8; 20], H160> for &[u8] {} +// impl TryDecodeProto<[u8; 256], H2048> for &[u8] {} +// impl TryDecodeProto<[u8; 32], H256> for &[u8] {} +// impl TryDecodeProto<[u8; 20], H160> for &[u8] {} -impl From<&BigInt> for web3::types::U256 { +impl TryDecodeProto<[u8; 32], B256> for &[u8] {} +impl TryDecodeProto<[u8; 256], B2048> for &[u8] {} +impl TryDecodeProto<[u8; 20], Address> for &[u8] {} + +impl From<&BigInt> for alloy::primitives::U256 { fn from(val: &BigInt) -> Self { - web3::types::U256::from_big_endian(&val.bytes) + alloy::primitives::U256::from_be_slice(&val.bytes) } } +// impl From<&BigInt> for web3::types::U256 { +// fn from(val: &BigInt) -> Self { +// web3::types::U256::from_big_endian(&val.bytes) +// } +// } + pub struct CallAt<'a> { call: &'a Call, block: &'a Block, @@ -70,10 +80,10 @@ impl<'a> TryInto for CallAt<'a> { .call .value .as_ref() - .map_or_else(|| U256::from(0), |v| v.into()), - gas_used: U256::from(self.call.gas_consumed), - input: Bytes(self.call.input.clone()), - output: Bytes(self.call.return_data.clone()), + .map_or_else(|| alloy::primitives::U256::from(0), |v| v.into()), + gas_used: self.call.gas_consumed, + input: Bytes::from(self.call.input.clone()), + output: Bytes::from(self.call.return_data.clone()), block_hash: self.block.hash.try_decode_proto("call block hash")?, block_number: self.block.number as i32, transaction_hash: Some(self.trace.hash.try_decode_proto("call transaction hash")?), @@ -82,40 +92,40 @@ impl<'a> TryInto for CallAt<'a> { } } -impl TryInto for Call { - type Error = Error; - - fn try_into(self) -> Result { - Ok(web3::types::Call { - from: self.caller.try_decode_proto("call from address")?, - to: self.address.try_decode_proto("call to address")?, - value: self - .value - .as_ref() - .map_or_else(|| U256::from(0), |v| v.into()), - gas: U256::from(self.gas_limit), - input: Bytes::from(self.input.clone()), - call_type: CallType::try_from(self.call_type) - .map_err(|_| graph::anyhow::anyhow!("invalid call type: {}", self.call_type))? - .into(), - }) - } -} - -impl From for web3::types::CallType { - fn from(val: CallType) -> Self { - match val { - CallType::Unspecified => web3::types::CallType::None, - CallType::Call => web3::types::CallType::Call, - CallType::Callcode => web3::types::CallType::CallCode, - CallType::Delegate => web3::types::CallType::DelegateCall, - CallType::Static => web3::types::CallType::StaticCall, - - // FIXME (SF): Really not sure what this should map to, we are using None for now, need to revisit - CallType::Create => web3::types::CallType::None, - } - } -} +// impl TryInto for Call { +// type Error = Error; + +// fn try_into(self) -> Result { +// Ok(web3::types::Call { +// from: self.caller.try_decode_proto("call from address")?, +// to: self.address.try_decode_proto("call to address")?, +// value: self +// .value +// .as_ref() +// .map_or_else(|| U256::from(0), |v| v.into()), +// gas: U256::from(self.gas_limit), +// input: Bytes::from(self.input.clone()), +// call_type: CallType::try_from(self.call_type) +// .map_err(|_| graph::anyhow::anyhow!("invalid call type: {}", self.call_type))? +// .into(), +// }) +// } +// } + +// impl From for web3::types::CallType { +// fn from(val: CallType) -> Self { +// match val { +// CallType::Unspecified => web3::types::CallType::None, +// CallType::Call => web3::types::CallType::Call, +// CallType::Callcode => web3::types::CallType::CallCode, +// CallType::Delegate => web3::types::CallType::DelegateCall, +// CallType::Static => web3::types::CallType::StaticCall, + +// // FIXME (SF): Really not sure what this should map to, we are using None for now, need to revisit +// CallType::Create => web3::types::CallType::None, +// } +// } +// } pub struct LogAt<'a> { log: &'a Log, @@ -129,45 +139,45 @@ impl<'a> LogAt<'a> { } } -impl<'a> TryInto for LogAt<'a> { - type Error = Error; - - fn try_into(self) -> Result { - Ok(web3::types::Log { - address: self.log.address.try_decode_proto("log address")?, - topics: self - .log - .topics - .iter() - .map(|t| t.try_decode_proto("topic")) - .collect::, Error>>()?, - data: Bytes::from(self.log.data.clone()), - block_hash: Some(self.block.hash.try_decode_proto("log block hash")?), - block_number: Some(U64::from(self.block.number)), - transaction_hash: Some(self.trace.hash.try_decode_proto("log transaction hash")?), - transaction_index: Some(U64::from(self.trace.index as u64)), - log_index: Some(U256::from(self.log.block_index)), - transaction_log_index: Some(U256::from(self.log.index)), - log_type: None, - removed: None, - }) - } -} - -impl TryFrom for Option { - type Error = Error; - - fn try_from(val: TransactionTraceStatus) -> Result { - match val { - TransactionTraceStatus::Unknown => Err(format_err!( - "Got a transaction trace with status UNKNOWN, datasource is broken" - )), - TransactionTraceStatus::Succeeded => Ok(Some(web3::types::U64::from(1))), - TransactionTraceStatus::Failed => Ok(Some(web3::types::U64::from(0))), - TransactionTraceStatus::Reverted => Ok(Some(web3::types::U64::from(0))), - } - } -} +// impl<'a> TryInto for LogAt<'a> { +// type Error = Error; + +// fn try_into(self) -> Result { +// Ok(web3::types::Log { +// address: self.log.address.try_decode_proto("log address")?, +// topics: self +// .log +// .topics +// .iter() +// .map(|t| t.try_decode_proto("topic")) +// .collect::, Error>>()?, +// data: Bytes::from(self.log.data.clone()), +// block_hash: Some(self.block.hash.try_decode_proto("log block hash")?), +// block_number: Some(U64::from(self.block.number)), +// transaction_hash: Some(self.trace.hash.try_decode_proto("log transaction hash")?), +// transaction_index: Some(U64::from(self.trace.index as u64)), +// log_index: Some(U256::from(self.log.block_index)), +// transaction_log_index: Some(U256::from(self.log.index)), +// log_type: None, +// removed: None, +// }) +// } +// } + +// impl TryFrom for Option { +// type Error = Error; + +// fn try_from(val: TransactionTraceStatus) -> Result { +// match val { +// TransactionTraceStatus::Unknown => Err(format_err!( +// "Got a transaction trace with status UNKNOWN, datasource is broken" +// )), +// TransactionTraceStatus::Succeeded => Ok(Some(web3::types::U64::from(1))), +// TransactionTraceStatus::Failed => Ok(Some(web3::types::U64::from(0))), +// TransactionTraceStatus::Reverted => Ok(Some(web3::types::U64::from(0))), +// } +// } +// } pub struct TransactionTraceAt<'a> { trace: &'a TransactionTrace, @@ -180,37 +190,37 @@ impl<'a> TransactionTraceAt<'a> { } } -impl<'a> TryInto for TransactionTraceAt<'a> { - type Error = Error; - - fn try_into(self) -> Result { - Ok(web3::types::Transaction { - hash: self.trace.hash.try_decode_proto("transaction hash")?, - nonce: U256::from(self.trace.nonce), - block_hash: Some(self.block.hash.try_decode_proto("transaction block hash")?), - block_number: Some(U64::from(self.block.number)), - transaction_index: Some(U64::from(self.trace.index as u64)), - from: Some( - self.trace - .from - .try_decode_proto("transaction from address")?, - ), - to: get_to_address(self.trace)?, - value: self.trace.value.as_ref().map_or(U256::zero(), |x| x.into()), - gas_price: self.trace.gas_price.as_ref().map(|x| x.into()), - gas: U256::from(self.trace.gas_limit), - input: Bytes::from(self.trace.input.clone()), - v: None, - r: None, - s: None, - raw: None, - access_list: None, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - transaction_type: None, - }) - } -} +// impl<'a> TryInto for TransactionTraceAt<'a> { +// type Error = Error; + +// fn try_into(self) -> Result { +// Ok(web3::types::Transaction { +// hash: self.trace.hash.try_decode_proto("transaction hash")?, +// nonce: U256::from(self.trace.nonce), +// block_hash: Some(self.block.hash.try_decode_proto("transaction block hash")?), +// block_number: Some(U64::from(self.block.number)), +// transaction_index: Some(U64::from(self.trace.index as u64)), +// from: Some( +// self.trace +// .from +// .try_decode_proto("transaction from address")?, +// ), +// to: get_to_address(self.trace)?, +// value: self.trace.value.as_ref().map_or(U256::zero(), |x| x.into()), +// gas_price: self.trace.gas_price.as_ref().map(|x| x.into()), +// gas: U256::from(self.trace.gas_limit), +// input: Bytes::from(self.trace.input.clone()), +// v: None, +// r: None, +// s: None, +// raw: None, +// access_list: None, +// max_fee_per_gas: None, +// max_priority_fee_per_gas: None, +// transaction_type: None, +// }) +// } +// } impl TryInto for &Block { type Error = Error; @@ -388,7 +398,7 @@ impl BlockHeader { match self.parent_hash.len() { 0 => None, _ => Some(BlockPtr::from(( - H256::from_slice(self.parent_hash.as_ref()), + B256::from_slice(self.parent_hash.as_ref()), self.number - 1, ))), } @@ -397,13 +407,13 @@ impl BlockHeader { impl<'a> From<&'a BlockHeader> for BlockPtr { fn from(b: &'a BlockHeader) -> BlockPtr { - BlockPtr::from((H256::from_slice(b.hash.as_ref()), b.number)) + BlockPtr::from((B256::from_slice(b.hash.as_ref()), b.number)) } } impl<'a> From<&'a Block> for BlockPtr { fn from(b: &'a Block) -> BlockPtr { - BlockPtr::from((H256::from_slice(b.hash.as_ref()), b.number)) + BlockPtr::from((B256::from_slice(b.hash.as_ref()), b.number)) } } @@ -537,7 +547,7 @@ mod test { } } -fn get_to_address(trace: &TransactionTrace) -> Result, Error> { +fn get_to_address(trace: &TransactionTrace) -> Result, Error> { // Try to detect contract creation transactions, which have no 'to' address let is_contract_creation = trace.to.len() == 0 || trace.calls.get(0).map_or(false, |call| { diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index 83322f2f1f8..aed4af76055 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -17,7 +17,7 @@ use graph::futures03::stream::FuturesOrdered; use graph::futures03::TryStreamExt; use graph::prelude::alloy::primitives::{Address, B256}; use graph::prelude::alloy::rpc::types::Log; -use graph::prelude::{alloy, b256_to_h256, Link, SubgraphManifestValidationError}; +use graph::prelude::{alloy, Link, SubgraphManifestValidationError}; use graph::slog::{debug, error, o, trace}; use graph::{abi, alloy_todo}; use itertools::Itertools; @@ -33,10 +33,8 @@ use tiny_keccak::{keccak256, Keccak}; use graph::{ blockchain::{self, Blockchain}, prelude::{ - async_trait, serde_json, warn, - web3::types::{H160, H256}, - BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, LightEthereumBlockExt, - LinkResolver, Logger, + async_trait, serde_json, warn, BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, + LightEthereumBlockExt, LinkResolver, Logger, }, }; @@ -132,7 +130,7 @@ impl blockchain::DataSource for DataSource { } fn address(&self) -> Option<&[u8]> { - self.address.as_ref().map(|x| x.as_bytes()) + self.address.as_ref().map(|x| x.as_slice()) } fn has_declared_calls(&self) -> bool { @@ -236,7 +234,7 @@ impl blockchain::DataSource for DataSource { } fn as_stored_dynamic_data_source(&self) -> StoredDynamicDataSource { - let param = self.address.map(|addr| addr.0.into()); + let param = self.address.map(|addr| addr.as_slice().into()); StoredDynamicDataSource { manifest_idx: self.manifest_idx, param, @@ -275,7 +273,7 @@ impl blockchain::DataSource for DataSource { let contract_abi = template.mapping.find_abi(&template.source.abi)?; - let address = param.map(|x| H160::from_slice(&x)); + let address = param.map(|x| Address::from_slice(&x)); Ok(DataSource { kind: template.kind.to_string(), network: template.network.as_ref().map(|s| s.to_string()), @@ -639,7 +637,7 @@ impl DataSource { return true; }; - ds_address == trigger_address + ds_address == *trigger_address } /// Checks if `trigger` matches this data source, and if so decodes it into a `MappingTrigger`. @@ -769,8 +767,8 @@ impl DataSource { let logging_extras = Arc::new(o! { "signature" => event_handler.event.to_string(), - "address" => format!("{}", &log.address), - "transaction" => format!("{}", &transaction.hash), + "address" => format!("{}", &log.address()), + "transaction" => format!("{}", &transaction.inner.tx_hash()), }); let handler = event_handler.handler.clone(); let calls = DeclaredCall::from_log_trigger( @@ -879,7 +877,7 @@ impl DataSource { let logging_extras = Arc::new(o! { "function" => handler.function.to_string(), "to" => format!("{}", &call.to), - "transaction" => format!("{}", &transaction.hash), + "transaction" => format!("{}", &transaction.inner.tx_hash()), }); Ok(Some(TriggerWithHandler::::new_with_logging_extras( MappingTrigger::Call { @@ -1414,7 +1412,7 @@ pub struct MappingEventHandler { #[serde(deserialize_with = "deserialize_b256_vec", default)] pub topic2: Option>, #[serde(deserialize_with = "deserialize_b256_vec", default)] - pub topic3: Option>, + pub topic3: Option>, pub handler: String, #[serde(default)] pub receipt: bool, @@ -1423,7 +1421,7 @@ pub struct MappingEventHandler { } // Custom deserializer for H256 fields that removes the '0x' prefix before parsing -fn deserialize_b256_vec<'de, D>(deserializer: D) -> Result>, D::Error> +fn deserialize_b256_vec<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { @@ -1450,9 +1448,9 @@ where } impl MappingEventHandler { - pub fn topic0(&self) -> H256 { + pub fn topic0(&self) -> B256 { self.topic0 - .unwrap_or_else(|| string_to_h256(&self.event.replace("indexed ", ""))) + .unwrap_or_else(|| string_to_b256(&self.event.replace("indexed ", ""))) } pub fn matches(&self, log: &Log) -> bool { @@ -1465,7 +1463,7 @@ impl MappingEventHandler { }; if let Some(topic0) = log.topics().get(0) { - return self.topic0() == b256_to_h256(*topic0) + return self.topic0() == *topic0 && matches_topic(1, &self.topic1) && matches_topic(2, &self.topic2) && matches_topic(3, &self.topic3); @@ -1482,8 +1480,8 @@ impl MappingEventHandler { } } -/// Hashes a string to a H256 hash. -fn string_to_h256(s: &str) -> H256 { +/// Hashes a string to a B256 hash. +fn string_to_b256(s: &str) -> B256 { let mut result = [0u8; 32]; let data = s.replace(' ', "").into_bytes(); let mut sponge = Keccak::new_keccak256(); @@ -1493,7 +1491,7 @@ fn string_to_h256(s: &str) -> H256 { // This was deprecated but the replacement seems to not be available in the // version web3 uses. #[allow(deprecated)] - H256::from_slice(&result) + B256::from_slice(&result) } #[derive(Clone, Debug, Default, Hash, Eq, PartialEq, Deserialize)] diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 09b174c6b31..505385adf9d 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -20,6 +20,8 @@ use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; use graph::prelude::alloy::consensus::BlockHeader; +use graph::prelude::alloy::primitives::Address; +use graph::prelude::alloy::rpc::types::Transaction; use graph::prelude::{ alloy::{ self, @@ -37,7 +39,7 @@ use graph::prelude::{ }, transports::{RpcError, TransportErrorKind}, }, - alloy_log_to_web3_log, h160_to_alloy_address, h256_to_b256, + alloy_log_to_web3_log, h256_to_b256, tokio::try_join, }; use graph::slog::o; @@ -49,13 +51,11 @@ use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ anyhow::{self, anyhow, bail, ensure, Context}, - async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, - web3::types::{Transaction, H256}, - BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, - TimeoutError, + async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn, BlockNumber, + ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger, TimeoutError, }, }; -use graph::{components::ethereum::*, prelude::web3::api::Web3, prelude::web3::types::H160}; +use graph::{components::ethereum::*, prelude::web3::api::Web3}; use itertools::Itertools; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::convert::TryFrom; @@ -568,9 +568,7 @@ impl EthereumAdapter { if !self.supports_eip_1898 { alloy::rpc::types::BlockId::number(block_ptr.number as u64) } else { - alloy::rpc::types::BlockId::hash(alloy::primitives::B256::new( - *block_ptr.hash_as_h256().as_fixed_bytes(), - )) + alloy::rpc::types::BlockId::hash(block_ptr.hash_as_b256()) } } @@ -932,13 +930,13 @@ impl EthereumAdapter { wildcard_signatures, } = call_filter; - let mut addresses: Vec = contract_addresses_function_signatures + let mut addresses: Vec
= contract_addresses_function_signatures .iter() .filter(|(_addr, (start_block, _fsigs))| start_block <= &to) .map(|(addr, (_start_block, _fsigs))| *addr) - .collect::>() + .collect::>() .into_iter() - .collect::>(); + .collect::>(); if addresses.is_empty() && wildcard_signatures.is_empty() { // The filter has no started data sources in the requested range, nothing to do. @@ -953,11 +951,6 @@ impl EthereumAdapter { addresses = vec![]; } - let addresses = addresses - .iter() - .map(|addr| h160_to_alloy_address(*addr)) - .collect(); - Box::new( eth.trace_stream(logger, subgraph_metrics, from, to, addresses) .try_filter_map(move |trace| { @@ -1546,7 +1539,7 @@ impl EthereumAdapterTrait for EthereumAdapter { fn log_call_error(logger: &Logger, e: &ContractCallError, call: &ContractCall) { match e { - ContractCallError::Web3Error(e) => error!(logger, + ContractCallError::AlloyError(e) => error!(logger, "Ethereum node returned an error when calling function \"{}\" of contract \"{}\": {}", call.function.name, call.contract_name, e), ContractCallError::Timeout => error!(logger, @@ -1778,7 +1771,7 @@ pub(crate) async fn blocks_with_triggers( let mut block_hashes: HashSet = triggers .iter() - .map(|trigger| h256_to_b256(trigger.block_hash())) + .map(|trigger| trigger.block_hash()) .collect(); let mut triggers_by_block: HashMap> = triggers.into_iter().fold(HashMap::new(), |mut map, t| { @@ -1875,7 +1868,7 @@ pub(crate) async fn get_calls( &logger, subgraph_metrics.clone(), ethereum_block.block.number(), - h256_to_b256(ethereum_block.block.hash_h256().unwrap()), + ethereum_block.block.hash(), ) .await? }; @@ -2038,14 +2031,14 @@ async fn filter_call_triggers_from_unsuccessful_transactions( let initial_number_of_triggers = block.trigger_data.len(); // Get the transaction hash from each call trigger - let transaction_hashes: BTreeSet = block + let transaction_hashes: BTreeSet = block .trigger_data .iter() .filter_map(|trigger| match trigger.as_chain() { Some(EthereumTrigger::Call(call_trigger)) => Some(call_trigger.transaction_hash), _ => None, }) - .collect::>>() + .collect::>>() .ok_or(anyhow!( "failed to obtain transaction hash from call triggers" ))?; @@ -2061,7 +2054,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions( BlockFinality::Final(ref block) => block .transactions() .iter() - .filter(|transaction| transaction_hashes.contains(&transaction.hash)) + .filter(|transaction| transaction_hashes.contains(transaction.inner.tx_hash())) .collect(), BlockFinality::NonFinal(_block_with_calls) => { unreachable!( @@ -2083,18 +2076,18 @@ async fn filter_call_triggers_from_unsuccessful_transactions( // We'll also need the receipts for those transactions. In this step we collect all receipts // we have in store for the current block. - let mut receipts = chain_store - .transaction_receipts_in_block(&block.ptr().hash_as_h256()) + let mut receipts: BTreeMap = chain_store + .transaction_receipts_in_block(&block.ptr().hash_as_b256()) .await? .into_iter() .map(|receipt| (receipt.transaction_hash, receipt)) - .collect::>(); + .collect::>(); // Do we have a receipt for each transaction under analysis? let mut receipts_and_transactions: Vec<(&Transaction, LightTransactionReceipt)> = Vec::new(); let mut transactions_without_receipt: Vec<&Transaction> = Vec::new(); for transaction in transactions.iter() { - if let Some(receipt) = receipts.remove(&transaction.hash) { + if let Some(receipt) = receipts.remove(transaction.inner.tx_hash()) { receipts_and_transactions.push((transaction, receipt)); } else { transactions_without_receipt.push(transaction); @@ -2105,7 +2098,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions( let futures = transactions_without_receipt .iter() .map(|transaction| async move { - fetch_receipt_from_ethereum_client(eth, h256_to_b256(transaction.hash)) + fetch_receipt_from_ethereum_client(eth, *transaction.inner.tx_hash()) .await .map(|receipt| (transaction, receipt)) }); @@ -2120,12 +2113,9 @@ async fn filter_call_triggers_from_unsuccessful_transactions( // additional Ethereum API calls for future scans on this block. // With all transactions and receipts in hand, we can evaluate the success of each transaction - let mut transaction_success: BTreeMap<&H256, bool> = BTreeMap::new(); + let mut transaction_success: BTreeMap<&B256, bool> = BTreeMap::new(); for (transaction, receipt) in receipts_and_transactions.into_iter() { - transaction_success.insert( - &transaction.hash, - evaluate_transaction_status(receipt.status), - ); + transaction_success.insert(&transaction.inner.tx_hash(), receipt.status); } // Confidence check: Did we inspect the status of all transactions? @@ -2523,8 +2513,8 @@ async fn get_logs_and_transactions( let optional_receipt = log .transaction_hash .and_then(|txn| transaction_receipts_by_hash.get(&txn).cloned()); - let web3_log = alloy_log_to_web3_log(log); - let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(web3_log), optional_receipt)); + + let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(log), optional_receipt)); log_triggers.push(value); } @@ -2624,11 +2614,10 @@ mod tests { use graph::alloy_todo; use graph::blockchain::BlockPtr; use graph::components::ethereum::BlockWrapper; - use graph::prelude::alloy::primitives::B256; + use graph::prelude::alloy::primitives::{Address, Bytes, B256}; use graph::prelude::alloy::providers::mock::Asserter; use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; - use graph::prelude::web3::types::{Address, Bytes, H256}; use graph::prelude::EthereumCall; use jsonrpc_core::serde_json::{self, Value}; use std::collections::HashSet; @@ -2858,11 +2847,11 @@ mod tests { } fn address(id: u64) -> Address { - Address::from_low_u64_be(id) + Address::from_slice(&id.to_le_bytes()) } - fn hash(id: u8) -> H256 { - H256::from([id; 32]) + fn hash(id: u8) -> B256 { + B256::from_slice(&[id; 32]) } fn bytes(value: Vec) -> Bytes { diff --git a/chain/ethereum/src/runtime/abi.rs b/chain/ethereum/src/runtime/abi.rs index d891b346173..c1af6b93feb 100644 --- a/chain/ethereum/src/runtime/abi.rs +++ b/chain/ethereum/src/runtime/abi.rs @@ -7,11 +7,9 @@ use graph::abi; use graph::prelude::alloy; use graph::prelude::alloy::network::ReceiptResponse; use graph::prelude::alloy::primitives::B256; +use graph::prelude::alloy::rpc::types::{Log, TransactionReceipt}; use graph::{ - prelude::{ - web3::types::{Log, TransactionReceipt, H256}, - BigInt, - }, + prelude::BigInt, runtime::{ asc_get, asc_new, gas::GasCounter, AscHeap, AscIndexId, AscPtr, AscType, DeterministicHostError, FromAscObj, HostExportError, IndexForAscTypeId, ToAscObj, @@ -24,7 +22,7 @@ use graph_runtime_wasm::asc_abi::class::{ }; use semver::Version; -type AscH256 = Uint8Array; +type AscB256 = Uint8Array; type AscH2048 = Uint8Array; pub struct AscLogParamArray(Array>); @@ -57,7 +55,7 @@ impl AscIndexId for AscLogParamArray { const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayEventParam; } -pub struct AscTopicArray(Array>); +pub struct AscTopicArray(Array>); impl AscType for AscTopicArray { fn to_asc_bytes(&self) -> Result, DeterministicHostError> { @@ -72,20 +70,6 @@ impl AscType for AscTopicArray { } } -impl ToAscObj for Vec { - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result { - let topics = self - .iter() - .map(|topic| asc_new(heap, topic, gas)) - .collect::, _>>()?; - Ok(AscTopicArray(Array::new(&topics, heap, gas)?)) - } -} - impl ToAscObj for &[alloy::primitives::B256] { fn to_asc_obj( &self, @@ -101,7 +85,7 @@ impl ToAscObj for &[alloy::primitives::B256] { } impl AscIndexId for AscTopicArray { - const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayH256; + const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayB256; } pub struct AscLogArray(Array>); @@ -119,7 +103,7 @@ impl AscType for AscLogArray { } } -impl ToAscObj for &[alloy::rpc::types::Log] { +impl ToAscObj for &[Log] { fn to_asc_obj( &self, heap: &mut H, @@ -133,19 +117,19 @@ impl ToAscObj for &[alloy::rpc::types::Log] { } } -impl ToAscObj for Vec { - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result { - let logs = self - .iter() - .map(|log| asc_new(heap, &log, gas)) - .collect::, _>>()?; - Ok(AscLogArray(Array::new(&logs, heap, gas)?)) - } -} +// impl ToAscObj for Vec { +// fn to_asc_obj( +// &self, +// heap: &mut H, +// gas: &GasCounter, +// ) -> Result { +// let logs = self +// .iter() +// .map(|log| asc_new(heap, &log, gas)) +// .collect::, _>>()?; +// Ok(AscLogArray(Array::new(&logs, heap, gas)?)) +// } +// } impl AscIndexId for AscLogArray { const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayLog; @@ -212,13 +196,13 @@ impl FromAscObj for UnresolvedContractCall { #[repr(C)] #[derive(AscType)] pub(crate) struct AscEthereumBlock { - pub hash: AscPtr, - pub parent_hash: AscPtr, - pub uncles_hash: AscPtr, + pub hash: AscPtr, + pub parent_hash: AscPtr, + pub uncles_hash: AscPtr, pub author: AscPtr, - pub state_root: AscPtr, - pub transactions_root: AscPtr, - pub receipts_root: AscPtr, + pub state_root: AscPtr, + pub transactions_root: AscPtr, + pub receipts_root: AscPtr, pub number: AscPtr, pub gas_used: AscPtr, pub gas_limit: AscPtr, @@ -236,13 +220,13 @@ impl AscIndexId for AscEthereumBlock { #[derive(AscType)] #[allow(non_camel_case_types)] pub(crate) struct AscEthereumBlock_0_0_6 { - pub hash: AscPtr, - pub parent_hash: AscPtr, - pub uncles_hash: AscPtr, + pub hash: AscPtr, + pub parent_hash: AscPtr, + pub uncles_hash: AscPtr, pub author: AscPtr, - pub state_root: AscPtr, - pub transactions_root: AscPtr, - pub receipts_root: AscPtr, + pub state_root: AscPtr, + pub transactions_root: AscPtr, + pub receipts_root: AscPtr, pub number: AscPtr, pub gas_used: AscPtr, pub gas_limit: AscPtr, @@ -261,7 +245,7 @@ impl AscIndexId for AscEthereumBlock_0_0_6 { #[derive(AscType)] #[allow(non_camel_case_types)] pub(crate) struct AscEthereumTransaction_0_0_1 { - pub hash: AscPtr, + pub hash: AscPtr, pub index: AscPtr, pub from: AscPtr, pub to: AscPtr, @@ -278,7 +262,7 @@ impl AscIndexId for AscEthereumTransaction_0_0_1 { #[derive(AscType)] #[allow(non_camel_case_types)] pub(crate) struct AscEthereumTransaction_0_0_2 { - pub hash: AscPtr, + pub hash: AscPtr, pub index: AscPtr, pub from: AscPtr, pub to: AscPtr, @@ -296,7 +280,7 @@ impl AscIndexId for AscEthereumTransaction_0_0_2 { #[derive(AscType)] #[allow(non_camel_case_types)] pub(crate) struct AscEthereumTransaction_0_0_6 { - pub hash: AscPtr, + pub hash: AscPtr, pub index: AscPtr, pub from: AscPtr, pub to: AscPtr, @@ -345,9 +329,9 @@ pub(crate) struct AscEthereumLog { pub address: AscPtr, pub topics: AscPtr, pub data: AscPtr, - pub block_hash: AscPtr, - pub block_number: AscPtr, - pub transaction_hash: AscPtr, + pub block_hash: AscPtr, + pub block_number: AscPtr, + pub transaction_hash: AscPtr, pub transaction_index: AscPtr, pub log_index: AscPtr, pub transaction_log_index: AscPtr, @@ -362,16 +346,16 @@ impl AscIndexId for AscEthereumLog { #[repr(C)] #[derive(AscType)] pub(crate) struct AscEthereumTransactionReceipt { - pub transaction_hash: AscPtr, + pub transaction_hash: AscPtr, pub transaction_index: AscPtr, - pub block_hash: AscPtr, + pub block_hash: AscPtr, pub block_number: AscPtr, pub cumulative_gas_used: AscPtr, pub gas_used: AscPtr, pub contract_address: AscPtr, pub logs: AscPtr, pub status: AscPtr, - pub root: AscPtr, + pub root: AscPtr, pub logs_bloom: AscPtr, } @@ -467,9 +451,9 @@ impl<'a> ToAscObj for EthereumBlockData<'a> { transactions_root: asc_new(heap, self.transactions_root(), gas)?, receipts_root: asc_new(heap, self.receipts_root(), gas)?, number: asc_new(heap, &BigInt::from(self.number()), gas)?, - gas_used: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_used()), gas)?, - gas_limit: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_limit()), gas)?, - timestamp: asc_new(heap, &BigInt::from_unsigned_u256(self.timestamp()), gas)?, + gas_used: asc_new(heap, &BigInt::from(self.gas_used()), gas)?, + gas_limit: asc_new(heap, &BigInt::from(self.gas_limit()), gas)?, + timestamp: asc_new(heap, &BigInt::from(self.timestamp()), gas)?, difficulty: asc_new(heap, &BigInt::from_unsigned_u256(self.difficulty()), gas)?, total_difficulty: asc_new( heap, @@ -499,9 +483,9 @@ impl<'a> ToAscObj for EthereumBlockData<'a> { transactions_root: asc_new(heap, self.transactions_root(), gas)?, receipts_root: asc_new(heap, self.receipts_root(), gas)?, number: asc_new(heap, &BigInt::from(self.number()), gas)?, - gas_used: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_used()), gas)?, - gas_limit: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_limit()), gas)?, - timestamp: asc_new(heap, &BigInt::from_unsigned_u256(self.timestamp()), gas)?, + gas_used: asc_new(heap, &BigInt::from(self.gas_used()), gas)?, + gas_limit: asc_new(heap, &BigInt::from(self.gas_limit()), gas)?, + timestamp: asc_new(heap, &BigInt::from(self.timestamp()), gas)?, difficulty: asc_new(heap, &BigInt::from_unsigned_u256(self.difficulty()), gas)?, total_difficulty: asc_new( heap, @@ -514,7 +498,7 @@ impl<'a> ToAscObj for EthereumBlockData<'a> { .unwrap_or(Ok(AscPtr::null()))?, base_fee_per_block: self .base_fee_per_gas() - .map(|base_fee| asc_new(heap, &BigInt::from_unsigned_u256(&base_fee), gas)) + .map(|base_fee| asc_new(heap, &BigInt::from(base_fee), gas)) .unwrap_or(Ok(AscPtr::null()))?, }) } @@ -528,15 +512,15 @@ impl<'a> ToAscObj for EthereumTransactionData<'a> ) -> Result { Ok(AscEthereumTransaction_0_0_1 { hash: asc_new(heap, self.hash(), gas)?, - index: asc_new(heap, &BigInt::from_unsigned_u128(self.index()), gas)?, + index: asc_new(heap, &BigInt::from(self.index()), gas)?, from: asc_new(heap, self.from(), gas)?, to: self .to() .map(|to| asc_new(heap, &to, gas)) .unwrap_or(Ok(AscPtr::null()))?, - value: asc_new(heap, &BigInt::from_unsigned_u256(self.value()), gas)?, - gas_limit: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_limit()), gas)?, - gas_price: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_price()), gas)?, + value: asc_new(heap, &BigInt::from_unsigned_u256(&self.value()), gas)?, + gas_limit: asc_new(heap, &BigInt::from(self.gas_limit()), gas)?, + gas_price: asc_new(heap, &BigInt::from(self.gas_price()), gas)?, }) } } @@ -549,15 +533,15 @@ impl<'a> ToAscObj for EthereumTransactionData<'a> ) -> Result { Ok(AscEthereumTransaction_0_0_2 { hash: asc_new(heap, self.hash(), gas)?, - index: asc_new(heap, &BigInt::from_unsigned_u128(self.index()), gas)?, + index: asc_new(heap, &BigInt::from(self.index()), gas)?, from: asc_new(heap, self.from(), gas)?, to: self .to() .map(|to| asc_new(heap, &to, gas)) .unwrap_or(Ok(AscPtr::null()))?, - value: asc_new(heap, &BigInt::from_unsigned_u256(self.value()), gas)?, - gas_limit: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_limit()), gas)?, - gas_price: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_price()), gas)?, + value: asc_new(heap, &BigInt::from_unsigned_u256(&self.value()), gas)?, + gas_limit: asc_new(heap, &BigInt::from(self.gas_limit()), gas)?, + gas_price: asc_new(heap, &BigInt::from(self.gas_price()), gas)?, input: asc_new(heap, self.input(), gas)?, }) } @@ -569,19 +553,21 @@ impl<'a> ToAscObj for EthereumTransactionData<'a> heap: &mut H, gas: &GasCounter, ) -> Result { + let value = self.value(); + Ok(AscEthereumTransaction_0_0_6 { hash: asc_new(heap, self.hash(), gas)?, - index: asc_new(heap, &BigInt::from_unsigned_u128(self.index()), gas)?, + index: asc_new(heap, &BigInt::from(self.index()), gas)?, from: asc_new(heap, self.from(), gas)?, to: self .to() .map(|to| asc_new(heap, &to, gas)) .unwrap_or(Ok(AscPtr::null()))?, - value: asc_new(heap, &BigInt::from_unsigned_u256(self.value()), gas)?, - gas_limit: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_limit()), gas)?, - gas_price: asc_new(heap, &BigInt::from_unsigned_u256(self.gas_price()), gas)?, + value: asc_new(heap, &BigInt::from_unsigned_u256(&self.value()), gas)?, + gas_limit: asc_new(heap, &BigInt::from(self.gas_limit()), gas)?, + gas_price: asc_new(heap, &BigInt::from(self.gas_price()), gas)?, input: asc_new(heap, self.input(), gas)?, - nonce: asc_new(heap, &BigInt::from_unsigned_u256(self.nonce()), gas)?, + nonce: asc_new(heap, &BigInt::from(self.nonce()), gas)?, }) } } @@ -600,12 +586,8 @@ where ) -> Result, HostExportError> { Ok(AscEthereumEvent { address: asc_new(heap, self.address(), gas)?, - log_index: asc_new(heap, &BigInt::from_unsigned_u256(self.log_index()), gas)?, - transaction_log_index: asc_new( - heap, - &BigInt::from_unsigned_u256(self.transaction_log_index()), - gas, - )?, + log_index: asc_new(heap, &BigInt::from(self.log_index()), gas)?, + transaction_log_index: asc_new(heap, &BigInt::from(self.transaction_log_index()), gas)?, log_type: self .log_type() .as_ref() @@ -659,98 +641,95 @@ where } } -impl<'a, T, B> ToAscObj> - for ( - EthereumEventData<'a>, - Option<&alloy::rpc::types::TransactionReceipt>, - ) -where - T: AscType + AscIndexId, - B: AscType + AscIndexId, - EthereumTransactionData<'a>: ToAscObj, - EthereumBlockData<'a>: ToAscObj, -{ - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result, HostExportError> { - let (event_data, optional_receipt) = self; - let AscEthereumEvent { - address, - log_index, - transaction_log_index, - log_type, - block, - transaction, - params, - } = event_data.to_asc_obj(heap, gas)?; - let receipt = if let Some(receipt_data) = optional_receipt { - asc_new(heap, receipt_data, gas)? - } else { - AscPtr::null() - }; - Ok(AscEthereumEvent_0_0_7 { - address, - log_index, - transaction_log_index, - log_type, - block, - transaction, - params, - receipt, - }) - } -} +// impl<'a, T, B> ToAscObj> +// for (EthereumEventData<'a>, Option<&TransactionReceipt>) +// where +// T: AscType + AscIndexId, +// B: AscType + AscIndexId, +// EthereumTransactionData<'a>: ToAscObj, +// EthereumBlockData<'a>: ToAscObj, +// { +// fn to_asc_obj( +// &self, +// heap: &mut H, +// gas: &GasCounter, +// ) -> Result, HostExportError> { +// let (event_data, optional_receipt) = self; +// let AscEthereumEvent { +// address, +// log_index, +// transaction_log_index, +// log_type, +// block, +// transaction, +// params, +// } = event_data.to_asc_obj(heap, gas)?; +// let receipt = if let Some(receipt_data) = optional_receipt { +// asc_new(heap, receipt_data, gas)? +// } else { +// AscPtr::null() +// }; +// Ok(AscEthereumEvent_0_0_7 { +// address, +// log_index, +// transaction_log_index, +// log_type, +// block, +// transaction, +// params, +// receipt, +// }) +// } +// } + +// impl ToAscObj for Log { +// fn to_asc_obj( +// &self, +// heap: &mut H, +// gas: &GasCounter, +// ) -> Result { +// Ok(AscEthereumLog { +// address: asc_new(heap, &self.address, gas)?, +// topics: asc_new(heap, &self.topics, gas)?, +// data: asc_new(heap, self.data.0.as_slice(), gas)?, +// block_hash: self +// .block_hash +// .map(|block_hash| asc_new(heap, &block_hash, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// block_number: self +// .block_number +// .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// transaction_hash: self +// .transaction_hash +// .map(|txn_hash| asc_new(heap, &txn_hash, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// transaction_index: self +// .transaction_index +// .map(|txn_index| asc_new(heap, &BigInt::from(txn_index), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// log_index: self +// .log_index +// .map(|log_index| asc_new(heap, &BigInt::from_unsigned_u256(&log_index), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// transaction_log_index: self +// .transaction_log_index +// .map(|index| asc_new(heap, &BigInt::from_unsigned_u256(&index), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// log_type: self +// .log_type +// .as_ref() +// .map(|log_type| asc_new(heap, &log_type, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// removed: self +// .removed +// .map(|removed| asc_new(heap, &AscWrapped { inner: removed }, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// }) +// } +// } impl ToAscObj for Log { - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result { - Ok(AscEthereumLog { - address: asc_new(heap, &self.address, gas)?, - topics: asc_new(heap, &self.topics, gas)?, - data: asc_new(heap, self.data.0.as_slice(), gas)?, - block_hash: self - .block_hash - .map(|block_hash| asc_new(heap, &block_hash, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - block_number: self - .block_number - .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - transaction_hash: self - .transaction_hash - .map(|txn_hash| asc_new(heap, &txn_hash, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - transaction_index: self - .transaction_index - .map(|txn_index| asc_new(heap, &BigInt::from(txn_index), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - log_index: self - .log_index - .map(|log_index| asc_new(heap, &BigInt::from_unsigned_u256(&log_index), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - transaction_log_index: self - .transaction_log_index - .map(|index| asc_new(heap, &BigInt::from_unsigned_u256(&index), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - log_type: self - .log_type - .as_ref() - .map(|log_type| asc_new(heap, &log_type, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - removed: self - .removed - .map(|removed| asc_new(heap, &AscWrapped { inner: removed }, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - }) - } -} - -impl ToAscObj for alloy::rpc::types::Log { fn to_asc_obj( &self, heap: &mut H, @@ -836,49 +815,49 @@ impl ToAscObj for &alloy::rpc::types::Transaction } } -impl ToAscObj for &TransactionReceipt { - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result { - Ok(AscEthereumTransactionReceipt { - transaction_hash: asc_new(heap, &self.transaction_hash, gas)?, - transaction_index: asc_new(heap, &BigInt::from(self.transaction_index), gas)?, - block_hash: self - .block_hash - .map(|block_hash| asc_new(heap, &block_hash, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - block_number: self - .block_number - .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - cumulative_gas_used: asc_new( - heap, - &BigInt::from_unsigned_u256(&self.cumulative_gas_used), - gas, - )?, - gas_used: self - .gas_used - .map(|gas_used| asc_new(heap, &BigInt::from_unsigned_u256(&gas_used), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - contract_address: self - .contract_address - .map(|contract_address| asc_new(heap, &contract_address, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - logs: asc_new(heap, &self.logs, gas)?, - status: self - .status - .map(|status| asc_new(heap, &BigInt::from(status), gas)) - .unwrap_or(Ok(AscPtr::null()))?, - root: self - .root - .map(|root| asc_new(heap, &root, gas)) - .unwrap_or(Ok(AscPtr::null()))?, - logs_bloom: asc_new(heap, self.logs_bloom.as_bytes(), gas)?, - }) - } -} +// impl ToAscObj for &TransactionReceipt { +// fn to_asc_obj( +// &self, +// heap: &mut H, +// gas: &GasCounter, +// ) -> Result { +// Ok(AscEthereumTransactionReceipt { +// transaction_hash: asc_new(heap, &self.transaction_hash, gas)?, +// transaction_index: asc_new(heap, &BigInt::from(self.transaction_index), gas)?, +// block_hash: self +// .block_hash +// .map(|block_hash| asc_new(heap, &block_hash, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// block_number: self +// .block_number +// .map(|block_number| asc_new(heap, &BigInt::from(block_number), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// cumulative_gas_used: asc_new( +// heap, +// &BigInt::from_unsigned_u256(&self.cumulative_gas_used), +// gas, +// )?, +// gas_used: self +// .gas_used +// .map(|gas_used| asc_new(heap, &BigInt::from_unsigned_u256(&gas_used), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// contract_address: self +// .contract_address +// .map(|contract_address| asc_new(heap, &contract_address, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// logs: asc_new(heap, &self.logs, gas)?, +// status: self +// .status +// .map(|status| asc_new(heap, &BigInt::from(status), gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// root: self +// .root +// .map(|root| asc_new(heap, &root, gas)) +// .unwrap_or(Ok(AscPtr::null()))?, +// logs_bloom: asc_new(heap, self.logs_bloom.as_bytes(), gas)?, +// }) +// } +// } impl<'a> ToAscObj for EthereumCallData<'a> { fn to_asc_obj( diff --git a/chain/ethereum/src/runtime/runtime_adapter.rs b/chain/ethereum/src/runtime/runtime_adapter.rs index e5f984e5300..050941f7ffd 100644 --- a/chain/ethereum/src/runtime/runtime_adapter.rs +++ b/chain/ethereum/src/runtime/runtime_adapter.rs @@ -228,11 +228,10 @@ fn eth_get_balance( match result { Ok(v) => { - let bigint = BigInt::from_unsigned_alloy_u256(&v); + let bigint = BigInt::from_unsigned_u256(&v); Ok(asc_new(ctx.heap, &bigint, &ctx.gas)?) } // Retry on any kind of error - Err(EthereumRpcError::Web3Error(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::AlloyError(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::Timeout) => Err(HostExportError::PossibleReorg( EthereumRpcError::Timeout.into(), @@ -265,7 +264,6 @@ fn eth_has_code( match result { Ok(v) => Ok(asc_new(ctx.heap, &AscWrapped { inner: v }, &ctx.gas)?), // Retry on any kind of error - Err(EthereumRpcError::Web3Error(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::AlloyError(e)) => Err(HostExportError::PossibleReorg(e.into())), Err(EthereumRpcError::Timeout) => Err(HostExportError::PossibleReorg( EthereumRpcError::Timeout.into(), @@ -330,7 +328,7 @@ fn eth_call( // Any error reported by the Ethereum node could be due to the block no longer being on // the main chain. This is very unespecific but we don't want to risk failing a // subgraph due to a transient error such as a reorg. - Err(ContractCallError::Web3Error(e)) => Err(HostExportError::PossibleReorg(anyhow::anyhow!( + Err(ContractCallError::AlloyError(e)) => Err(HostExportError::PossibleReorg(anyhow::anyhow!( "Ethereum node returned an error when calling function \"{}\" of contract \"{}\": {}", unresolved_call.function_name, unresolved_call.contract_name, diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index 9aa75c10fa5..6d22bc97bc4 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -5,10 +5,11 @@ use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger}, components::ethereum::BlockWrapper, prelude::{ - web3::{ - self, - types::{Address, Bytes, Log, Transaction, H160, H256, U64}, + alloy::{ + primitives::{Address, Bytes, B256}, + rpc::types::Log, }, + rand::{self, Rng}, EthereumCall, }, slog::{self, o, Logger}, @@ -19,15 +20,37 @@ use crate::{ trigger::{EthereumBlockTriggerType, EthereumTrigger, LogRef}, }; +pub trait Random { + fn random() -> Self; +} + +impl Random for B256 { + fn random() -> Self { + let mut rng = rand::rng(); + let mut bytes = [0u8; 32]; + rng.fill(&mut bytes); + Self::from(bytes) + } +} + +impl Random for Address { + fn random() -> Self { + let mut rng = rand::rng(); + let mut bytes = [0u8; 20]; + rng.fill(&mut bytes); + Self::from(bytes) + } +} + #[test] fn test_trigger_ordering() { let block1 = EthereumTrigger::Block( - BlockPtr::from((H256::random(), 1u64)), + BlockPtr::from((B256::random(), 1u64)), EthereumBlockTriggerType::End, ); let block2 = EthereumTrigger::Block( - BlockPtr::from((H256::random(), 0u64)), + BlockPtr::from((B256::random(), 0u64)), EthereumBlockTriggerType::WithCallTo(Address::random()), ); @@ -37,7 +60,7 @@ fn test_trigger_ordering() { let mut call2 = EthereumCall::default(); call2.transaction_index = 2; - call2.input = Bytes(vec![0]); + call2.input = Bytes::from(vec![0]); let call2 = EthereumTrigger::Call(Arc::new(call2)); let mut call3 = EthereumCall::default(); @@ -48,23 +71,24 @@ fn test_trigger_ordering() { let mut call4 = EthereumCall::default(); call4.transaction_index = 2; // different than call2 so they don't get mistaken as the same - call4.input = Bytes(vec![1]); + call4.input = Bytes::from(vec![1]); let call4 = EthereumTrigger::Call(Arc::new(call4)); fn create_log(tx_index: u64, log_index: u64) -> Arc { - Arc::new(Log { - address: H160::default(), - topics: vec![], - data: Bytes::default(), - block_hash: Some(H256::zero()), - block_number: Some(U64::zero()), - transaction_hash: Some(H256::zero()), - transaction_index: Some(tx_index.into()), - log_index: Some(log_index.into()), - transaction_log_index: Some(log_index.into()), - log_type: Some("".into()), - removed: Some(false), - }) + // Arc::new(Log { + // address: H160::default(), + // topics: vec![], + // data: Bytes::default(), + // block_hash: Some(H256::zero()), + // block_number: Some(U64::zero()), + // transaction_hash: Some(H256::zero()), + // transaction_index: Some(tx_index.into()), + // log_index: Some(log_index.into()), + // transaction_log_index: Some(log_index.into()), + // log_type: Some("".into()), + // removed: Some(false), + // }) + alloy_todo!() } // Event with transaction_index 1 and log_index 0; @@ -127,12 +151,12 @@ fn test_trigger_ordering() { #[test] fn test_trigger_dedup() { let block1 = EthereumTrigger::Block( - BlockPtr::from((H256::random(), 1u64)), + BlockPtr::from((B256::random(), 1u64)), EthereumBlockTriggerType::End, ); let block2 = EthereumTrigger::Block( - BlockPtr::from((H256::random(), 0u64)), + BlockPtr::from((B256::random(), 0u64)), EthereumBlockTriggerType::WithCallTo(Address::random()), ); @@ -157,19 +181,20 @@ fn test_trigger_dedup() { let call4 = EthereumTrigger::Call(Arc::new(call4)); fn create_log(tx_index: u64, log_index: u64) -> Arc { - Arc::new(Log { - address: H160::default(), - topics: vec![], - data: Bytes::default(), - block_hash: Some(H256::zero()), - block_number: Some(U64::zero()), - transaction_hash: Some(H256::zero()), - transaction_index: Some(tx_index.into()), - log_index: Some(log_index.into()), - transaction_log_index: Some(log_index.into()), - log_type: Some("".into()), - removed: Some(false), - }) + // Arc::new(Log { + // address: H160::default(), + // topics: vec![], + // data: Bytes::default(), + // block_hash: Some(H256::zero()), + // block_number: Some(U64::zero()), + // transaction_hash: Some(H256::zero()), + // transaction_index: Some(tx_index.into()), + // log_index: Some(log_index.into()), + // transaction_log_index: Some(log_index.into()), + // log_type: Some("".into()), + // removed: Some(false), + // }) + alloy_todo!() } let log1 = EthereumTrigger::Log(LogRef::FullLog(create_log(1, 0), None)); @@ -199,13 +224,13 @@ fn test_trigger_dedup() { let logger = Logger::root(slog::Discard, o!()); - let mut b: web3::types::Block = Default::default(); + // let mut b: web3::types::Block = Default::default(); - // This is necessary because inside of BlockWithTriggers::new - // there's a log for both fields. So just using Default above - // gives None on them. - b.number = Some(Default::default()); - b.hash = Some(Default::default()); + // // This is necessary because inside of BlockWithTriggers::new + // // there's a log for both fields. So just using Default above + // // gives None on them. + // b.number = Some(Default::default()); + // b.hash = Some(Default::default()); #[allow(unused_variables)] let b = alloy_todo!(); diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index 8cac5cc443d..50a40a74552 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -1,20 +1,16 @@ use graph::abi; +use graph::alloy_todo; use graph::blockchain::MappingTriggerTrait; use graph::blockchain::TriggerData; use graph::data::subgraph::API_VERSION_0_0_2; use graph::data::subgraph::API_VERSION_0_0_6; use graph::data::subgraph::API_VERSION_0_0_7; use graph::data_source::common::DeclaredCall; -use graph::prelude::alloy::primitives::Address; -use graph::prelude::alloy::primitives::B256; +use graph::prelude::alloy::consensus::Transaction as TransactioTrait; +use graph::prelude::alloy::primitives::{Address, B256, U256}; use graph::prelude::alloy::rpc::types::Log; +use graph::prelude::alloy::rpc::types::Transaction; use graph::prelude::alloy::rpc::types::TransactionReceipt as AlloyTransactionReceipt; -use graph::prelude::web3::types::Transaction; -use graph::prelude::web3::types::H160; -use graph::prelude::web3::types::H256; -use graph::prelude::web3::types::U128; -use graph::prelude::web3::types::U256; -use graph::prelude::web3::types::U64; use graph::prelude::BlockNumber; use graph::prelude::BlockPtr; use graph::prelude::LightEthereumBlock; @@ -38,7 +34,7 @@ use crate::runtime::abi::AscEthereumTransaction_0_0_1; use crate::runtime::abi::AscEthereumTransaction_0_0_2; use crate::runtime::abi::AscEthereumTransaction_0_0_6; -static U256_DEFAULT: U256 = U256::zero(); +static U256_DEFAULT: U256 = U256::ZERO; pub enum MappingTrigger { Log { @@ -262,7 +258,7 @@ impl LogRef { } pub fn address(&self) -> &Address { - &self.log().address + &self.log().inner.address } } @@ -305,14 +301,14 @@ impl EthereumTrigger { EthereumTrigger::Block(block_ptr, _) => block_ptr.number, EthereumTrigger::Call(call) => call.block_number, EthereumTrigger::Log(log_ref) => { - i32::try_from(log_ref.block_number().unwrap().as_u64()).unwrap() + i32::try_from(log_ref.block_number().unwrap()).unwrap() } } } - pub fn block_hash(&self) -> H256 { + pub fn block_hash(&self) -> B256 { match self { - EthereumTrigger::Block(block_ptr, _) => block_ptr.hash_as_h256(), + EthereumTrigger::Block(block_ptr, _) => block_ptr.hash_as_b256(), EthereumTrigger::Call(call) => call.block_hash, EthereumTrigger::Log(log_ref) => log_ref.block_hash().unwrap(), } @@ -325,7 +321,7 @@ impl EthereumTrigger { Some(address) } EthereumTrigger::Call(call) => Some(&call.to), - EthereumTrigger::Log(log_ref) => Some(&log_ref.address()), + EthereumTrigger::Log(log_ref) => Some(log_ref.address()), // Unfiltered block triggers match any data source address. EthereumTrigger::Block(_, EthereumBlockTriggerType::End) => None, EthereumTrigger::Block(_, EthereumBlockTriggerType::Start) => None, @@ -356,23 +352,21 @@ impl Ord for EthereumTrigger { // Calls vs. events are logged by their tx index; // if they are from the same transaction, events come first (Self::Call(a), Self::Log(b)) - if a.transaction_index == b.transaction_index().unwrap().as_u64() => + if a.transaction_index == b.transaction_index().unwrap() => { Ordering::Greater } (Self::Log(a), Self::Call(b)) - if a.transaction_index().unwrap().as_u64() == b.transaction_index => + if a.transaction_index().unwrap() == b.transaction_index => { Ordering::Less } - (Self::Call(a), Self::Log(b)) => a - .transaction_index - .cmp(&b.transaction_index().unwrap().as_u64()), - (Self::Log(a), Self::Call(b)) => a - .transaction_index() - .unwrap() - .as_u64() - .cmp(&b.transaction_index), + (Self::Call(a), Self::Log(b)) => { + a.transaction_index.cmp(&b.transaction_index().unwrap()) + } + (Self::Log(a), Self::Call(b)) => { + a.transaction_index().unwrap().cmp(&b.transaction_index) + } } } } @@ -403,7 +397,7 @@ impl TriggerData for EthereumTrigger { } fn address_match(&self) -> Option<&[u8]> { - self.address().map(|address| address.as_bytes()) + self.address().map(|address| address.as_slice()) } } @@ -420,68 +414,70 @@ impl<'a> From<&'a LightEthereumBlock> for EthereumBlockData<'a> { } impl<'a> EthereumBlockData<'a> { - pub fn hash(&self) -> &H256 { - self.block.inner().hash.as_ref().unwrap() + pub fn hash(&self) -> &B256 { + &self.block.inner().header.hash } - pub fn parent_hash(&self) -> &H256 { - &self.block.inner().parent_hash + pub fn parent_hash(&self) -> &B256 { + &self.block.inner().header.parent_hash } - pub fn uncles_hash(&self) -> &H256 { - &self.block.inner().uncles_hash + pub fn uncles_hash(&self) -> &B256 { + // &self.block.inner().header.uncles_hash + alloy_todo!() } - pub fn author(&self) -> &H160 { - &self.block.inner().author + pub fn author(&self) -> &Address { + &self.block.inner().header.beneficiary } - pub fn state_root(&self) -> &H256 { - &self.block.inner().state_root + pub fn state_root(&self) -> &B256 { + &self.block.inner().header.state_root } - pub fn transactions_root(&self) -> &H256 { - &self.block.inner().transactions_root + pub fn transactions_root(&self) -> &B256 { + &self.block.inner().header.transactions_root } - pub fn receipts_root(&self) -> &H256 { - &self.block.inner().receipts_root + pub fn receipts_root(&self) -> &B256 { + &self.block.inner().header.receipts_root } - pub fn number(&self) -> U64 { - self.block.inner().number.unwrap() + pub fn number(&self) -> u64 { + self.block.number_u64() } - pub fn gas_used(&self) -> &U256 { - &self.block.inner().gas_used + pub fn gas_used(&self) -> u64 { + self.block.inner().header.gas_used } - pub fn gas_limit(&self) -> &U256 { - &self.block.inner().gas_limit + pub fn gas_limit(&self) -> u64 { + self.block.inner().header.gas_limit } - pub fn timestamp(&self) -> &U256 { - &self.block.inner().timestamp + pub fn timestamp(&self) -> u64 { + self.block.inner().header.timestamp } pub fn difficulty(&self) -> &U256 { - &self.block.inner().difficulty + &self.block.inner().header.difficulty } pub fn total_difficulty(&self) -> &U256 { self.block .inner() + .header .total_difficulty .as_ref() .unwrap_or(&U256_DEFAULT) } pub fn size(&self) -> &Option { - &self.block.inner().size + &self.block.inner().header.size } - pub fn base_fee_per_gas(&self) -> &Option { - &self.block.inner().base_fee_per_gas + pub fn base_fee_per_gas(&self) -> &Option { + &self.block.inner().header.base_fee_per_gas } } @@ -498,43 +494,43 @@ impl<'a> EthereumTransactionData<'a> { EthereumTransactionData { tx } } - pub fn hash(&self) -> &H256 { - &self.tx.hash + pub fn hash(&self) -> &B256 { + &self.tx.inner.tx_hash() } - pub fn index(&self) -> U128 { - self.tx.transaction_index.unwrap().as_u64().into() + pub fn index(&self) -> u64 { + self.tx.transaction_index.unwrap() } - pub fn from(&self) -> &H160 { + pub fn from(&self) -> &Address { // unwrap: this is always `Some` for txns that have been mined // (see https://github.com/tomusdrw/rust-web3/pull/407) - self.tx.from.as_ref().unwrap() + self.tx.inner.signer_ref() } - pub fn to(&self) -> &Option { - &self.tx.to + pub fn to(&self) -> Option
{ + self.tx.to() } - pub fn value(&self) -> &U256 { - &self.tx.value + pub fn value(&self) -> U256 { + self.tx.value() } - pub fn gas_limit(&self) -> &U256 { - &self.tx.gas + pub fn gas_limit(&self) -> u64 { + self.tx.gas_limit() } - pub fn gas_price(&self) -> &U256 { + pub fn gas_price(&self) -> u128 { // EIP-1559 made this optional. - self.tx.gas_price.as_ref().unwrap_or(&U256_DEFAULT) + self.tx.inner.gas_price().unwrap_or(0) } pub fn input(&self) -> &[u8] { - &self.tx.input.0 + self.tx.input() } - pub fn nonce(&self) -> &U256 { - &self.tx.nonce + pub fn nonce(&self) -> u64 { + self.tx.nonce() } } @@ -563,25 +559,26 @@ impl<'a> EthereumEventData<'a> { } pub fn address(&self) -> &Address { - &self.log.address + &self.log.inner.address } - pub fn log_index(&self) -> &U256 { - self.log.log_index.as_ref().unwrap_or(&U256_DEFAULT) + pub fn log_index(&self) -> u64 { + self.log.log_index.unwrap_or(0) } - pub fn transaction_log_index(&self) -> &U256 { + pub fn transaction_log_index(&self) -> u64 { // We purposely use the `log_index` here. Geth does not support // `transaction_log_index`, and subgraphs that use it only care that // it identifies the log, the specific value is not important. Still // this will change the output of subgraphs that use this field. // // This was initially changed in commit b95c6953 - self.log.log_index.as_ref().unwrap_or(&U256_DEFAULT) + self.log.log_index.unwrap_or(0) } pub fn log_type(&self) -> &Option { - &self.log.log_type + // &self.log.log_type + alloy_todo!() } } diff --git a/chain/near/src/codec.rs b/chain/near/src/codec.rs index 6f0f2f7af4d..905495e7ae3 100644 --- a/chain/near/src/codec.rs +++ b/chain/near/src/codec.rs @@ -7,18 +7,17 @@ pub mod pbcodec; pub mod substreams_triggers; use graph::{ - blockchain::Block as BlockchainBlock, - blockchain::{BlockPtr, BlockTime}, - prelude::{hex, web3::types::H256, BlockNumber}, + blockchain::{Block as BlockchainBlock, BlockPtr, BlockTime}, + prelude::{alloy::primitives::B256, hex, BlockNumber}, }; use std::convert::TryFrom; use std::fmt::LowerHex; pub use pbcodec::*; -impl From<&CryptoHash> for H256 { +impl From<&CryptoHash> for B256 { fn from(input: &CryptoHash) -> Self { - H256::from_slice(&input.bytes) + B256::from_slice(&input.bytes) } } @@ -31,7 +30,7 @@ impl LowerHex for &CryptoHash { impl BlockHeader { pub fn parent_ptr(&self) -> Option { match (self.prev_hash.as_ref(), self.prev_height) { - (Some(hash), number) => Some(BlockPtr::from((H256::from(hash), number))), + (Some(hash), number) => Some(BlockPtr::from((B256::from(hash), number))), _ => None, } } @@ -39,7 +38,7 @@ impl BlockHeader { impl<'a> From<&'a BlockHeader> for BlockPtr { fn from(b: &'a BlockHeader) -> BlockPtr { - BlockPtr::from((H256::from(b.hash.as_ref().unwrap()), b.height)) + BlockPtr::from((B256::from(b.hash.as_ref().unwrap()), b.height)) } } diff --git a/chain/near/src/trigger.rs b/chain/near/src/trigger.rs index 364b9061038..71b0d46a768 100644 --- a/chain/near/src/trigger.rs +++ b/chain/near/src/trigger.rs @@ -2,8 +2,8 @@ use graph::blockchain::Block; use graph::blockchain::MappingTriggerTrait; use graph::blockchain::TriggerData; use graph::derive::CheapClone; +use graph::prelude::alloy::primitives::B256; use graph::prelude::hex; -use graph::prelude::web3::types::H256; use graph::prelude::BlockNumber; use graph::runtime::HostExportError; use graph::runtime::{asc_new, gas::GasCounter, AscHeap, AscPtr}; @@ -78,10 +78,10 @@ impl NearTrigger { } } - pub fn block_hash(&self) -> H256 { + pub fn block_hash(&self) -> B256 { match self { - NearTrigger::Block(block) => block.ptr().hash_as_h256(), - NearTrigger::Receipt(receipt) => receipt.block.ptr().hash_as_h256(), + NearTrigger::Block(block) => block.ptr().hash_as_b256(), + NearTrigger::Receipt(receipt) => receipt.block.ptr().hash_as_b256(), } } diff --git a/graph/src/abi/event_ext.rs b/graph/src/abi/event_ext.rs index 59ae560a8a2..a9a1cd32f71 100644 --- a/graph/src/abi/event_ext.rs +++ b/graph/src/abi/event_ext.rs @@ -1,12 +1,9 @@ use std::collections::VecDeque; use alloy::json_abi::Event; -use alloy::primitives::LogData; +use alloy::rpc::types::Log; use anyhow::anyhow; -use anyhow::Context; use anyhow::Result; -use itertools::Itertools; -use web3::types::Log; use crate::abi::{DynSolParam, DynSolValue}; @@ -16,7 +13,7 @@ pub trait EventExt { impl EventExt for Event { fn decode_log(&self, log: &Log) -> Result> { - let log_data = log_to_log_data(log)?; + let log_data = log.data(); let decoded_event = alloy::dyn_abi::EventExt::decode_log(self, &log_data)?; let mut indexed: VecDeque = decoded_event.indexed.into(); let mut body: VecDeque = decoded_event.body.into(); @@ -48,39 +45,31 @@ impl EventExt for Event { } } -fn log_to_log_data(log: &Log) -> Result { - let topics = log - .topics - .iter() - .map(|x| x.to_fixed_bytes().into()) - .collect_vec(); - - let data = log.data.0.clone().into(); - - LogData::new(topics, data).context("log has an invalid number of topics") -} - #[cfg(test)] mod tests { use alloy::dyn_abi::DynSolValue; use alloy::primitives::U256; + use crate::alloy_todo; + use super::*; - fn make_log(topics: &[[u8; 32]], data: Vec) -> Log { - Log { - address: [1; 20].into(), - topics: topics.iter().map(Into::into).collect(), - data: data.into(), - block_hash: None, - block_number: None, - transaction_hash: None, - transaction_index: None, - log_index: None, - transaction_log_index: None, - log_type: None, - removed: None, - } + fn make_log(_topics: &[[u8; 32]], _data: Vec) -> Log { + // Log { + // address: [1; 20].into(), + // topics: topics.iter().map(Into::into).collect(), + // data: data.into(), + // block_hash: None, + // block_number: None, + // transaction_hash: None, + // transaction_index: None, + // log_index: None, + // transaction_log_index: None, + // log_type: None, + // removed: None, + // } + + alloy_todo!() } #[test] diff --git a/graph/src/abi/mod.rs b/graph/src/abi/mod.rs index 88fe14b1806..9bedeb0e3b2 100644 --- a/graph/src/abi/mod.rs +++ b/graph/src/abi/mod.rs @@ -12,7 +12,7 @@ pub use alloy::json_abi::JsonAbi; pub use alloy::json_abi::StateMutability; pub use alloy::primitives::I256; -pub use alloy::primitives::U256; +pub use alloy::primitives::U256 as AlloyU256; pub use self::event_ext::EventExt; pub use self::function_ext::FunctionExt; diff --git a/graph/src/blockchain/mock.rs b/graph/src/blockchain/mock.rs index 01487c42113..e66c3e28cbf 100644 --- a/graph/src/blockchain/mock.rs +++ b/graph/src/blockchain/mock.rs @@ -16,6 +16,7 @@ use crate::{ DataSourceTemplateInfo, StoreError, }, }; +use alloy::primitives::{B256, U256}; use anyhow::{Error, Result}; use async_trait::async_trait; use serde::Deserialize; @@ -26,7 +27,6 @@ use std::{ convert::TryFrom, sync::Arc, }; -use web3::types::H256; use super::{ block_stream::{self, BlockStream, FirehoseCursor}, @@ -73,7 +73,7 @@ pub fn test_ptr(n: BlockNumber) -> BlockPtr { } pub fn test_ptr_reorged(n: BlockNumber, reorg_n: u32) -> BlockPtr { - let mut hash = H256::from_low_u64_be(n as u64); + let mut hash = B256::from(U256::from(n as u64)); hash[0..4].copy_from_slice(&reorg_n.to_be_bytes()); BlockPtr { hash: hash.into(), @@ -520,7 +520,7 @@ impl ChainStore for MockChainStore { async fn attempt_chain_head_update( self: Arc, _ancestor_count: BlockNumber, - ) -> Result, Error> { + ) -> Result, Error> { unimplemented!() } async fn blocks(self: Arc, _hashes: Vec) -> Result, Error> { @@ -560,7 +560,7 @@ impl ChainStore for MockChainStore { } async fn transaction_receipts_in_block( &self, - _block_ptr: &H256, + _block_ptr: &B256, ) -> Result, StoreError> { unimplemented!() } diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index c4b538f1188..d9f428ce28c 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -1,4 +1,4 @@ -use alloy::primitives::B256; +use alloy::primitives::{B256, U256}; use anyhow::anyhow; use diesel::deserialize::FromSql; use diesel::pg::Pg; @@ -10,7 +10,6 @@ use serde::{Deserialize, Deserializer}; use std::convert::TryFrom; use std::time::Duration; use std::{fmt, str::FromStr}; -use web3::types::{Block as Web3Block, H256, U256, U64}; use crate::components::ethereum::BlockWrapper; @@ -35,8 +34,8 @@ impl BlockHash { &self.0 } - pub fn as_h256(&self) -> H256 { - H256::from_slice(self.as_slice()) + pub fn as_b256(&self) -> B256 { + B256::from_slice(self.as_slice()) } /// Encodes the block hash into a hexadecimal string **without** a "0x" @@ -48,7 +47,7 @@ impl BlockHash { } pub fn zero() -> Self { - Self::from(H256::zero()) + Self::from(B256::ZERO) } } @@ -86,11 +85,11 @@ impl fmt::LowerHex for BlockHash { } } -impl From for BlockHash { - fn from(hash: H256) -> Self { - BlockHash(hash.as_bytes().into()) - } -} +// impl From for BlockHash { +// fn from(hash: H256) -> Self { +// BlockHash(hash.as_bytes().into()) +// } +// } impl From> for BlockHash { fn from(bytes: Vec) -> Self { @@ -179,12 +178,12 @@ impl BlockPtr { self.number } - // FIXME: - // - // workaround for arweave - pub fn hash_as_h256(&self) -> H256 { - H256::from_slice(&self.hash_slice()[..32]) - } + // // FIXME: + // // + // // workaround for arweave + // pub fn hash_as_h256(&self) -> H256 { + // H256::from_slice(&self.hash_slice()[..32]) + // } pub fn hash_as_b256(&self) -> B256 { B256::from_slice(&self.hash_slice()[..32]) @@ -220,27 +219,27 @@ impl slog::Value for BlockPtr { impl From for BlockPtr { fn from(b: BlockWrapper) -> BlockPtr { - BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) + BlockPtr::from((b.hash_b256().unwrap(), b.number_u64() as i32)) } } impl From<&BlockWrapper> for BlockPtr { fn from(b: &BlockWrapper) -> BlockPtr { - BlockPtr::from((b.hash_h256().unwrap(), b.number_u64().unwrap() as i32)) + BlockPtr::from((b.hash_b256().unwrap(), b.number_u64() as i32)) } } -impl From> for BlockPtr { - fn from(b: Web3Block) -> BlockPtr { - BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) - } -} +// impl From> for BlockPtr { +// fn from(b: Web3Block) -> BlockPtr { +// BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) +// } +// } -impl<'a, T> From<&'a Web3Block> for BlockPtr { - fn from(b: &'a Web3Block) -> BlockPtr { - BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) - } -} +// impl<'a, T> From<&'a Web3Block> for BlockPtr { +// fn from(b: &'a Web3Block) -> BlockPtr { +// BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) +// } +// } impl From<(Vec, i32)> for BlockPtr { fn from((bytes, number): (Vec, i32)) -> Self { @@ -251,8 +250,17 @@ impl From<(Vec, i32)> for BlockPtr { } } -impl From<(H256, i32)> for BlockPtr { - fn from((hash, number): (H256, i32)) -> BlockPtr { +impl From<(B256, i32)> for BlockPtr { + fn from((hash, number): (alloy::primitives::B256, i32)) -> BlockPtr { + BlockPtr { + hash: hash.into(), + number, + } + } +} +impl From<(B256, u64)> for BlockPtr { + fn from((hash, number): (alloy::primitives::B256, u64)) -> BlockPtr { + let number = i32::try_from(number).unwrap(); BlockPtr { hash: hash.into(), number, @@ -260,8 +268,11 @@ impl From<(H256, i32)> for BlockPtr { } } -impl From<(alloy::primitives::B256, i32)> for BlockPtr { - fn from((hash, number): (alloy::primitives::B256, i32)) -> BlockPtr { + + +impl From<(alloy::primitives::B256, i64)> for BlockPtr { + fn from((hash, number): (alloy::primitives::B256, i64)) -> BlockPtr { + let number = i32::try_from(number).unwrap(); BlockPtr { hash: hash.into(), number, @@ -289,24 +300,6 @@ impl From<(Vec, i64)> for BlockPtr { } } -impl From<(H256, u64)> for BlockPtr { - fn from((hash, number): (H256, u64)) -> BlockPtr { - let number = i32::try_from(number).unwrap(); - - BlockPtr::from((hash, number)) - } -} - -impl From<(H256, i64)> for BlockPtr { - fn from((hash, number): (H256, i64)) -> BlockPtr { - if number < 0 { - panic!("block number out of range: {}", number); - } - - BlockPtr::from((hash, number as u64)) - } -} - impl TryFrom<(&str, i64)> for BlockPtr { type Error = anyhow::Error; @@ -322,14 +315,14 @@ impl TryFrom<(&[u8], i64)> for BlockPtr { type Error = anyhow::Error; fn try_from((bytes, number): (&[u8], i64)) -> Result { - let hash = if bytes.len() == H256::len_bytes() { - H256::from_slice(bytes) + let hash = if bytes.len() == B256::len_bytes() { + B256::from_slice(bytes) } else { return Err(anyhow!( - "invalid H256 value `{}` has {} bytes instead of {}", + "invalid B256 value `{}` has {} bytes instead of {}", hex::encode(bytes), bytes.len(), - H256::len_bytes() + B256::len_bytes() )); }; Ok(BlockPtr::from((hash, number))) @@ -346,9 +339,9 @@ impl IntoValue for BlockPtr { } } -impl From for H256 { +impl From for B256 { fn from(ptr: BlockPtr) -> Self { - ptr.hash_as_h256() + ptr.hash_as_b256() } } @@ -433,12 +426,12 @@ impl ExtendedBlockPtr { self.number } - pub fn hash_as_h256(&self) -> H256 { - H256::from_slice(&self.hash_slice()[..32]) + pub fn hash_as_b256(&self) -> B256 { + B256::from_slice(&self.hash_slice()[..32]) } - pub fn parent_hash_as_h256(&self) -> H256 { - H256::from_slice(&self.parent_hash_slice()[..32]) + pub fn parent_hash_as_b256(&self) -> B256 { + B256::from_slice(&self.parent_hash_slice()[..32]) } pub fn hash_slice(&self) -> &[u8] { @@ -497,55 +490,7 @@ impl IntoValue for ExtendedBlockPtr { } } -impl TryFrom<(Option, Option, H256, U256)> for ExtendedBlockPtr { - type Error = anyhow::Error; - - fn try_from(tuple: (Option, Option, H256, U256)) -> Result { - let (hash_opt, number_opt, parent_hash, timestamp_u256) = tuple; - - let hash = hash_opt.ok_or_else(|| anyhow!("Block hash is missing"))?; - let number = number_opt - .ok_or_else(|| anyhow!("Block number is missing"))? - .as_u64(); - - let block_number = - i32::try_from(number).map_err(|_| anyhow!("Block number out of range"))?; - - // Convert `U256` to `BlockTime` - let secs = - i64::try_from(timestamp_u256).map_err(|_| anyhow!("Timestamp out of range for i64"))?; - let block_time = BlockTime::since_epoch(secs, 0); - - Ok(ExtendedBlockPtr { - hash: hash.into(), - number: block_number, - parent_hash: parent_hash.into(), - timestamp: block_time, - }) - } -} - -impl TryFrom<(H256, i32, H256, U256)> for ExtendedBlockPtr { - type Error = anyhow::Error; - - fn try_from(tuple: (H256, i32, H256, U256)) -> Result { - let (hash, block_number, parent_hash, timestamp_u256) = tuple; - - // Convert `U256` to `BlockTime` - let secs = - i64::try_from(timestamp_u256).map_err(|_| anyhow!("Timestamp out of range for i64"))?; - let block_time = BlockTime::since_epoch(secs, 0); - - Ok(ExtendedBlockPtr { - hash: hash.into(), - number: block_number, - parent_hash: parent_hash.into(), - timestamp: block_time, - }) - } -} - -impl TryFrom<(alloy::primitives::B256, i32, alloy::primitives::B256, u64)> for ExtendedBlockPtr { +impl TryFrom<(B256, i32, B256, u64)> for ExtendedBlockPtr { type Error = anyhow::Error; fn try_from( @@ -554,9 +499,8 @@ impl TryFrom<(alloy::primitives::B256, i32, alloy::primitives::B256, u64)> for E let (hash, block_number, parent_hash, timestamp) = tuple; // Convert timestamp to `BlockTime` - let secs = - i64::try_from(timestamp).map_err(|_| anyhow!("Timestamp out of range for i64"))?; - let block_time = BlockTime::since_epoch(secs, 0); + let secs = timestamp; + let block_time = BlockTime::since_epoch(secs as i64, 0); Ok(ExtendedBlockPtr { hash: hash.into(), @@ -566,11 +510,6 @@ impl TryFrom<(alloy::primitives::B256, i32, alloy::primitives::B256, u64)> for E }) } } -impl From for H256 { - fn from(ptr: ExtendedBlockPtr) -> Self { - ptr.hash_as_h256() - } -} impl From for BlockNumber { fn from(ptr: ExtendedBlockPtr) -> Self { @@ -595,7 +534,7 @@ impl Default for ChainIdentifier { fn default() -> Self { Self { net_version: String::default(), - genesis_block_hash: BlockHash::from(H256::zero()), + genesis_block_hash: BlockHash::from(B256::ZERO), } } } diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index 8dbfcdae856..8a76dd1c7ed 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -1,19 +1,17 @@ use alloy::{ - primitives::B256, - rpc::types::trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}, + primitives::{Address, Bytes, B256, U256, U64}, + rpc::types::{ + trace::parity::{Action, LocalizedTransactionTrace, TraceOutput}, + Log, Transaction, + }, }; use serde::{Deserialize, Serialize}; use std::sync::Arc; -use web3::types::{Address, Bytes, Log, Transaction, U256, U64}; use crate::{ alloy_todo, blockchain::{BlockPtr, BlockTime}, - prelude::{ - alloy::rpc::types::Block as AlloyBlock, alloy_address_to_h160, b256_to_h256, h256_to_b256, - BlockNumber, - }, - util::conversions::{alloy_bytes_to_web3_bytes, alloy_u256_to_web3_u256, u64_to_web3_u256}, + prelude::{alloy::rpc::types::Block as AlloyBlock, BlockNumber}, }; #[allow(dead_code)] @@ -25,7 +23,7 @@ impl BlockWrapper { Self(block) } - pub fn hash_h256(&self) -> Option { + pub fn hash_b256(&self) -> Option { alloy_todo!() // self.0.hash } @@ -34,9 +32,8 @@ impl BlockWrapper { self.0.header.hash } - pub fn number_u64(&self) -> Option { - alloy_todo!() - // self.0.number.map(|n| n.as_u64()) + pub fn number_u64(&self) -> u64 { + self.0.header.number } pub fn number_web3_u64(&self) -> Option { @@ -50,13 +47,11 @@ impl BlockWrapper { } pub fn transactions(&self) -> &[Transaction] { - alloy_todo!() - // &self.0.transactions + &self.0.transactions.as_transactions().unwrap() } - pub fn inner(&self) -> &web3::types::Block { - alloy_todo!() - // &self.0 + pub fn inner(&self) -> &AlloyBlock { + &self.0 } } @@ -64,7 +59,7 @@ pub type LightEthereumBlock = BlockWrapper; pub trait LightEthereumBlockExt { fn number(&self) -> BlockNumber; - fn transaction_for_log(&self, log: &alloy::rpc::types::Log) -> Option; + fn transaction_for_log(&self, log: &Log) -> Option; fn transaction_for_call(&self, call: &EthereumCall) -> Option; fn parent_ptr(&self) -> Option; fn format(&self) -> String; @@ -157,7 +152,7 @@ impl EthereumBlockWithCalls { .ethereum_block .transaction_receipts .iter() - .find(|txn| txn.transaction_hash == h256_to_b256(call_transaction_hash)) + .find(|txn| txn.transaction_hash == call_transaction_hash) .ok_or(anyhow::anyhow!( "failed to find the receipt for this transaction" ))?; @@ -187,7 +182,7 @@ pub struct EthereumCall { pub from: Address, pub to: Address, pub value: U256, - pub gas_used: U256, + pub gas_used: u64, pub input: Bytes, pub output: Bytes, pub block_number: BlockNumber, @@ -223,15 +218,15 @@ impl EthereumCall { let transaction_index = trace.transaction_position? as u64; Some(EthereumCall { - from: alloy_address_to_h160(call.from), - to: alloy_address_to_h160(call.to), - value: alloy_u256_to_web3_u256(call.value), - gas_used: u64_to_web3_u256(gas_used), - input: alloy_bytes_to_web3_bytes(call.input.clone()), - output: alloy_bytes_to_web3_bytes(output), + from: call.from, + to: call.to, + value: call.value, + gas_used: gas_used, + input: call.input.clone(), + output: output, block_number: trace.block_number? as BlockNumber, - block_hash: trace.block_hash.map(|h| b256_to_h256(h))?, - transaction_hash: trace.transaction_hash.map(|h| b256_to_h256(h)), + block_hash: trace.block_hash?, + transaction_hash: trace.transaction_hash, transaction_index, }) } @@ -239,13 +234,13 @@ impl EthereumCall { impl From for BlockPtr { fn from(b: EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash_h256().unwrap(), b.block.number())) + BlockPtr::from((b.block.hash_b256().unwrap(), b.block.number())) } } impl<'a> From<&'a EthereumBlock> for BlockPtr { fn from(b: &'a EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash_h256().unwrap(), b.block.number())) + BlockPtr::from((b.block.hash_b256().unwrap(), b.block.number())) } } diff --git a/graph/src/components/store/mod.rs b/graph/src/components/store/mod.rs index 66a020ead21..b94689e9842 100644 --- a/graph/src/components/store/mod.rs +++ b/graph/src/components/store/mod.rs @@ -3,6 +3,7 @@ mod err; mod traits; pub mod write; +use alloy::primitives::Address; use diesel::deserialize::FromSql; use diesel::pg::Pg; use diesel::serialize::{Output, ToSql}; @@ -1163,7 +1164,7 @@ pub struct CachedEthereumCall { pub block_ptr: BlockPtr, /// The address to the called contract. - pub contract_address: web3::types::Address, + pub contract_address: Address, /// The encoded return value of this call. pub return_value: Vec, diff --git a/graph/src/components/store/traits.rs b/graph/src/components/store/traits.rs index 59f59afb281..2bb913fc209 100644 --- a/graph/src/components/store/traits.rs +++ b/graph/src/components/store/traits.rs @@ -3,7 +3,6 @@ use std::ops::Range; use anyhow::Error; use async_trait::async_trait; -use web3::types::{Address, H256}; use super::*; use crate::blockchain::block_stream::{EntitySourceOperation, FirehoseCursor}; @@ -19,7 +18,10 @@ use crate::data::store::ethereum::call; use crate::data::store::QueryObject; use crate::data::subgraph::{status, DeploymentFeatures}; use crate::data::{query::QueryTarget, subgraph::schema::*}; -use crate::prelude::{DeploymentState, NodeId, QueryExecutionError, SubgraphName}; +use crate::prelude::{ + alloy::primitives::{Address, B256}, + DeploymentState, NodeId, QueryExecutionError, SubgraphName, +}; use crate::schema::{ApiSchema, InputSchema}; pub trait SubscriptionManager: Send + Sync + 'static { @@ -520,7 +522,7 @@ pub trait ChainStore: ChainHeadStore { async fn attempt_chain_head_update( self: Arc, ancestor_count: BlockNumber, - ) -> Result, Error>; + ) -> Result, Error>; /// Returns the blocks present in the store. async fn blocks( @@ -590,7 +592,7 @@ pub trait ChainStore: ChainHeadStore { /// Tries to retrieve all transactions receipts for a given block. async fn transaction_receipts_in_block( &self, - block_ptr: &H256, + block_ptr: &B256, ) -> Result, StoreError>; /// Clears call cache of the chain for the given `from` and `to` block number. diff --git a/graph/src/components/subgraph/proof_of_indexing/mod.rs b/graph/src/components/subgraph/proof_of_indexing/mod.rs index 36eeabc22cd..57731586ed8 100644 --- a/graph/src/components/subgraph/proof_of_indexing/mod.rs +++ b/graph/src/components/subgraph/proof_of_indexing/mod.rs @@ -86,6 +86,7 @@ mod tests { prelude::{BlockPtr, DeploymentHash, Value}, schema::InputSchema, }; + use alloy::primitives::{Address, B256}; use maplit::hashmap; use online::ProofOfIndexingFinisher; use reference::*; @@ -95,7 +96,6 @@ mod tests { use stable_hash_legacy::utils::stable_hash as stable_hash_legacy; use std::collections::HashMap; use std::convert::TryInto; - use web3::types::{Address, H256}; /// Verify that the stable hash of a reference and online implementation match fn check(case: Case, cache: &mut HashMap) { @@ -219,7 +219,7 @@ mod tests { fast: "dced49c45eac68e8b3d8f857928e7be6c270f2db8b56b0d7f27ce725100bae01", data: PoI { subgraph_id: DeploymentHash::new("test").unwrap(), - block_hash: H256::repeat_byte(1), + block_hash: B256::repeat_byte(1), causality_regions: HashMap::new(), indexer: None, }, @@ -231,7 +231,7 @@ mod tests { fast: "8bb3373fb55e02bde3202bac0eeecf1bd9a676856a4dd6667bd809aceda41885", data: PoI { subgraph_id: DeploymentHash::new("test").unwrap(), - block_hash: H256::repeat_byte(1), + block_hash: B256::repeat_byte(1), causality_regions: hashmap! { "eth".to_owned() => PoICausalityRegion { blocks: vec! [ @@ -258,7 +258,7 @@ mod tests { fast: "8b0097ad96b21f7e4bd8dcc41985e6e5506b808f1185016ab1073dd8745238ce", data: PoI { subgraph_id: DeploymentHash::new("b").unwrap(), - block_hash: H256::repeat_byte(3), + block_hash: B256::repeat_byte(3), causality_regions: hashmap! { "eth".to_owned() => PoICausalityRegion { blocks: vec! [ @@ -296,7 +296,7 @@ mod tests { fast: "2041af28678e68406247a5cfb5fe336947da75256c79b35c2f61fc7985091c0e", data: PoI { subgraph_id: DeploymentHash::new("b").unwrap(), - block_hash: H256::repeat_byte(3), + block_hash: B256::repeat_byte(3), causality_regions: hashmap! { "eth".to_owned() => PoICausalityRegion { blocks: vec! [ @@ -358,7 +358,7 @@ mod tests { fast: "421ef30a03be64014b9eef2b999795dcabfc601368040df855635e7886eb3822", data: PoI { subgraph_id: DeploymentHash::new("test").unwrap(), - block_hash: H256::repeat_byte(1), + block_hash: B256::repeat_byte(1), causality_regions: hashmap! { "eth".to_owned() => PoICausalityRegion { blocks: vec! [ diff --git a/graph/src/components/subgraph/proof_of_indexing/online.rs b/graph/src/components/subgraph/proof_of_indexing/online.rs index ebf7a65e2f9..f9bd8b5f18d 100644 --- a/graph/src/components/subgraph/proof_of_indexing/online.rs +++ b/graph/src/components/subgraph/proof_of_indexing/online.rs @@ -9,6 +9,7 @@ use crate::{ prelude::{debug, BlockNumber, DeploymentHash, Logger, ENV_VARS}, util::stable_hash_glue::AsBytes, }; +use alloy::primitives::Address; use sha2::{Digest, Sha256}; use stable_hash::{fast::FastStableHasher, FieldAddress, StableHash, StableHasher}; use stable_hash_legacy::crypto::{Blake3SeqNo, SetHasher}; @@ -18,7 +19,6 @@ use stable_hash_legacy::prelude::{ use std::collections::HashMap; use std::convert::TryInto; use std::fmt; -use web3::types::Address; pub struct BlockEventStream { vec_length: u64, @@ -278,7 +278,7 @@ impl ProofOfIndexingFinisher { state.write(&AsBytes(block.hash_slice()), &[2]); // Add PoI.indexer - state.write(&indexer.as_ref().map(|i| AsBytes(i.as_bytes())), &[3]); + state.write(&indexer.as_ref().map(|i| AsBytes(i.as_slice())), &[3]); ProofOfIndexingFinisher { block_number: block.number, diff --git a/graph/src/components/subgraph/proof_of_indexing/reference.rs b/graph/src/components/subgraph/proof_of_indexing/reference.rs index 5c7d269d7a7..b54b4c7613e 100644 --- a/graph/src/components/subgraph/proof_of_indexing/reference.rs +++ b/graph/src/components/subgraph/proof_of_indexing/reference.rs @@ -1,8 +1,9 @@ +use alloy::primitives::{Address, B256}; + use super::ProofOfIndexingEvent; use crate::prelude::DeploymentHash; use crate::util::stable_hash_glue::{impl_stable_hash, AsBytes}; use std::collections::HashMap; -use web3::types::{Address, H256}; /// The PoI is the StableHash of this struct. This reference implementation is /// mostly here just to make sure that the online implementation is @@ -12,22 +13,22 @@ use web3::types::{Address, H256}; pub struct PoI<'a> { pub causality_regions: HashMap>, pub subgraph_id: DeploymentHash, - pub block_hash: H256, + pub block_hash: B256, pub indexer: Option
, } -fn h256_as_bytes(val: &H256) -> AsBytes<&[u8]> { - AsBytes(val.as_bytes()) +fn b256_as_bytes(val: &B256) -> AsBytes<&[u8]> { + AsBytes(val.as_slice()) } fn indexer_opt_as_bytes(val: &Option
) -> Option> { - val.as_ref().map(|v| AsBytes(v.as_bytes())) + val.as_ref().map(|v| AsBytes(v.as_slice())) } impl_stable_hash!(PoI<'_> { causality_regions, subgraph_id, - block_hash: h256_as_bytes, + block_hash: b256_as_bytes, indexer: indexer_opt_as_bytes }); diff --git a/graph/src/components/transaction_receipt.rs b/graph/src/components/transaction_receipt.rs index 07c25694750..2f8dc84e6fc 100644 --- a/graph/src/components/transaction_receipt.rs +++ b/graph/src/components/transaction_receipt.rs @@ -3,55 +3,29 @@ //! This module exposes the [`LightTransactionReceipt`] type, which holds basic information about //! the retrieved transaction receipts. -use web3::types::{TransactionReceipt, H256, U256, U64}; - -use crate::{ - prelude::b256_to_h256, - util::conversions::{bool_to_web3_u64, u64_to_web3_u256, web3_u64_from_option}, -}; +use alloy::primitives::B256; +use alloy::rpc::types::TransactionReceipt; /// Like web3::types::Receipt, but with fewer fields. #[derive(Debug, PartialEq, Eq)] pub struct LightTransactionReceipt { - pub transaction_hash: H256, - pub transaction_index: U64, - pub block_hash: Option, - pub block_number: Option, - pub gas_used: Option, - pub status: Option, + pub transaction_hash: B256, + pub transaction_index: u64, + pub block_hash: Option, + pub block_number: Option, + pub gas_used: u64, + pub status: bool, } impl From for LightTransactionReceipt { - fn from(receipt: TransactionReceipt) -> Self { - let TransactionReceipt { - transaction_hash, - transaction_index, - block_hash, - block_number, - gas_used, - status, - .. - } = receipt; - LightTransactionReceipt { - transaction_hash, - transaction_index, - block_hash, - block_number, - gas_used, - status, - } - } -} - -impl From for LightTransactionReceipt { fn from(receipt: alloy::rpc::types::TransactionReceipt) -> Self { LightTransactionReceipt { - transaction_hash: b256_to_h256(receipt.transaction_hash), - transaction_index: web3_u64_from_option(receipt.transaction_index), - block_hash: receipt.block_hash.map(b256_to_h256), - block_number: Some(web3_u64_from_option(receipt.block_number)), - gas_used: Some(u64_to_web3_u256(receipt.gas_used)), - status: Some(bool_to_web3_u64(receipt.status())), + transaction_hash: receipt.transaction_hash, + transaction_index: receipt.transaction_index.unwrap(), + block_hash: receipt.block_hash, + block_number: receipt.block_number, + gas_used: receipt.gas_used, + status: receipt.status(), } } } diff --git a/graph/src/data/graphql/values.rs b/graph/src/data/graphql/values.rs index 7f15d26dc98..b4923d6ce26 100644 --- a/graph/src/data/graphql/values.rs +++ b/graph/src/data/graphql/values.rs @@ -1,3 +1,4 @@ +use alloy::primitives::Address; use anyhow::{anyhow, Error}; use std::collections::HashMap; use std::convert::TryFrom; @@ -6,7 +7,6 @@ use std::str::FromStr; use crate::blockchain::BlockHash; use crate::data::value::Object; use crate::prelude::{r, BigInt}; -use web3::types::H160; pub trait TryFromValue: Sized { fn try_from_value(value: &r::Value) -> Result; @@ -74,16 +74,11 @@ impl TryFromValue for i32 { } } -impl TryFromValue for H160 { +impl TryFromValue for Address { fn try_from_value(value: &r::Value) -> Result { match value { - r::Value::String(s) => { - // `H160::from_str` takes a hex string with no leading `0x`. - let string = s.trim_start_matches("0x"); - H160::from_str(string).map_err(|e| { - anyhow!("Cannot parse Address/H160 value from string `{}`: {}", s, e) - }) - } + r::Value::String(s) => Address::from_str(s) + .map_err(|e| anyhow!("Cannot parse Address/H160 value from string `{}`: {}", s, e)), _ => Err(anyhow!( "Cannot parse value into an Address/H160: {:?}", value diff --git a/graph/src/data/store/ethereum.rs b/graph/src/data/store/ethereum.rs index 263389c1dfb..268b5c28d7d 100644 --- a/graph/src/data/store/ethereum.rs +++ b/graph/src/data/store/ethereum.rs @@ -1,7 +1,7 @@ use super::scalar; use crate::derive::CheapClone; use crate::prelude::*; -use web3::types::{Address, Bytes, H2048, H256, H64, U64}; +use alloy::primitives::{aliases::B2048, Address, Bytes, B256, B64, U64}; impl From
for Value { fn from(address: Address) -> Value { @@ -9,27 +9,27 @@ impl From
for Value { } } -impl From for Value { - fn from(hash: H64) -> Value { +impl From for Value { + fn from(hash: B64) -> Value { Value::Bytes(scalar::Bytes::from(hash.as_ref())) } } -impl From for Value { - fn from(hash: H256) -> Value { +impl From for Value { + fn from(hash: B256) -> Value { Value::Bytes(scalar::Bytes::from(hash.as_ref())) } } -impl From for Value { - fn from(hash: H2048) -> Value { +impl From for Value { + fn from(hash: B2048) -> Value { Value::Bytes(scalar::Bytes::from(hash.as_ref())) } } impl From for Value { fn from(bytes: Bytes) -> Value { - Value::Bytes(scalar::Bytes::from(bytes.0.as_slice())) + Value::Bytes(scalar::Bytes::from(bytes.as_ref())) } } diff --git a/graph/src/data/store/scalar/bigint.rs b/graph/src/data/store/scalar/bigint.rs index 3d46fb2b861..1109d761706 100644 --- a/graph/src/data/store/scalar/bigint.rs +++ b/graph/src/data/store/scalar/bigint.rs @@ -3,8 +3,8 @@ use serde::{self, Deserialize, Serialize}; use stable_hash::utils::AsInt; use stable_hash::StableHash; use thiserror::Error; -use web3::types::*; +use crate::prelude::alloy::primitives::{U128, U256, U64}; use std::convert::{TryFrom, TryInto}; use std::fmt; use std::ops::{Add, BitAnd, BitOr, Div, Mul, Rem, Shl, Shr, Sub}; @@ -173,28 +173,19 @@ impl BigInt { } pub fn from_unsigned_u128(n: U128) -> Self { - let mut bytes: [u8; 16] = [0; 16]; - n.to_little_endian(&mut bytes); + let bytes: [u8; U128::BYTES] = n.to_le_bytes(); // Unwrap: 128 bits is much less than BigInt::MAX_BITS BigInt::from_unsigned_bytes_le(&bytes).unwrap() } pub fn from_unsigned_u256(n: &U256) -> Self { - let mut bytes: [u8; 32] = [0; 32]; - n.to_little_endian(&mut bytes); - // Unwrap: 256 bits is much less than BigInt::MAX_BITS - BigInt::from_unsigned_bytes_le(&bytes).unwrap() - } - - pub fn from_unsigned_alloy_u256(n: &alloy::primitives::U256) -> Self { - let bytes = n.to_le_bytes_trimmed_vec(); + let bytes: [u8; U256::BYTES] = n.to_le_bytes(); // Unwrap: 256 bits is much less than BigInt::MAX_BITS BigInt::from_unsigned_bytes_le(&bytes).unwrap() } pub fn from_signed_u256(n: &U256) -> Self { - let mut bytes: [u8; 32] = [0; 32]; - n.to_little_endian(&mut bytes); + let bytes: [u8; U256::BYTES] = n.to_le_bytes(); BigInt::from_signed_bytes_le(&bytes).unwrap() } @@ -207,9 +198,9 @@ impl BigInt { ); let mut i_bytes: [u8; 32] = [255; 32]; i_bytes[..bytes.len()].copy_from_slice(&bytes); - U256::from_little_endian(&i_bytes) + U256::from_le_slice(&i_bytes) } else { - U256::from_little_endian(&bytes) + U256::from_le_slice(&bytes) } } @@ -220,7 +211,7 @@ impl BigInt { "negative value encountered for U256: {}", self ); - U256::from_little_endian(&bytes) + U256::from_le_slice(&bytes) } pub fn pow(self, exponent: u8) -> Result { @@ -242,6 +233,12 @@ impl From for BigInt { } } +impl From for BigInt { + fn from(i: u128) -> BigInt { + BigInt::unchecked_new(i.into()) + } +} + impl From for BigInt { fn from(i: i64) -> BigInt { BigInt::unchecked_new(i.into()) @@ -255,7 +252,7 @@ impl From for BigInt { /// handle signed U64s, we should add the same /// `{to,from}_{signed,unsigned}_u64` methods that we have for U64. fn from(n: U64) -> BigInt { - BigInt::from(n.as_u64()) + BigInt::from(n.to::()) } } @@ -371,8 +368,9 @@ impl GasSizeOf for BigInt { #[cfg(test)] mod test { + use alloy::primitives::U64; + use super::{super::test::same_stable_hash, BigInt}; - use web3::types::U64; #[test] fn bigint_to_from_u64() { diff --git a/graph/src/data/subgraph/mod.rs b/graph/src/data/subgraph/mod.rs index 77c8ba67d36..e7233b5af79 100644 --- a/graph/src/data/subgraph/mod.rs +++ b/graph/src/data/subgraph/mod.rs @@ -3,6 +3,7 @@ pub mod schema; /// API version and spec version. pub mod api_version; +use alloy::primitives::Address; pub use api_version::*; pub mod features; @@ -29,7 +30,6 @@ use std::{ }; use thiserror::Error; use wasmparser; -use web3::types::Address; use crate::{ bail, diff --git a/graph/src/data_source/common.rs b/graph/src/data_source/common.rs index 84347f3b125..873dc8b41f8 100644 --- a/graph/src/data_source/common.rs +++ b/graph/src/data_source/common.rs @@ -4,6 +4,9 @@ use crate::abi::FunctionExt; use crate::blockchain::block_stream::EntitySourceOperation; use crate::prelude::{BlockPtr, Value}; use crate::{components::link_resolver::LinkResolver, data::value::Word, prelude::Link}; +use alloy::primitives::Address; +use alloy::primitives::U256; +use alloy::rpc::types::Log; use anyhow::{anyhow, Context, Error}; use graph_derive::CheapClone; use lazy_static::lazy_static; @@ -13,8 +16,6 @@ use serde::de; use serde::Deserialize; use slog::Logger; use std::{str::FromStr, sync::Arc}; -use web3::types::Address; -use web3::types::{Log, H160}; #[derive(Clone, Debug, PartialEq)] pub struct MappingABI { @@ -129,11 +130,15 @@ impl CallDecl { self.expr.validate_args() } - pub fn address_for_log(&self, log: &Log, params: &[abi::DynSolParam]) -> Result { + pub fn address_for_log( + &self, + log: &Log, + params: &[abi::DynSolParam], + ) -> Result { let address = match &self.expr.address { CallArg::HexAddress(address) => *address, CallArg::Ethereum(arg) => match arg { - EthereumArg::Address => log.address, + EthereumArg::Address => log.address(), EthereumArg::Param(name) => { let value = ¶ms .iter() @@ -168,13 +173,9 @@ impl CallDecl { .args .iter() .map(|arg| match arg { - CallArg::HexAddress(address) => { - Ok(DynSolValue::Address(address.to_fixed_bytes().into())) - } + CallArg::HexAddress(address) => Ok(DynSolValue::Address(*address)), CallArg::Ethereum(arg) => match arg { - EthereumArg::Address => { - Ok(DynSolValue::Address(log.address.to_fixed_bytes().into())) - } + EthereumArg::Address => Ok(DynSolValue::Address(log.address())), EthereumArg::Param(name) => { let value = params .iter() @@ -219,7 +220,7 @@ impl CallDecl { pub fn address_for_entity_handler( &self, entity: &EntitySourceOperation, - ) -> Result { + ) -> Result { match &self.expr.address { // Static hex address - just return it directly CallArg::HexAddress(address) => Ok(*address), @@ -240,7 +241,7 @@ impl CallDecl { // Make sure it's a bytes value and convert to address match value { Value::Bytes(bytes) => { - let address = H160::from_slice(bytes.as_slice()); + let address = Address::from_slice(bytes.as_slice()); Ok(address) } _ => Err(anyhow!("param '{name}' must be an address")), @@ -302,13 +303,11 @@ impl CallDecl { /// Converts a hex address to a token, ensuring it matches the expected parameter type. fn process_hex_address( &self, - address: H160, + address: Address, expected_type: &abi::DynSolType, ) -> Result { match expected_type { - abi::DynSolType::Address => { - Ok(abi::DynSolValue::Address(address.to_fixed_bytes().into())) - } + abi::DynSolType::Address => Ok(abi::DynSolValue::Address(address)), _ => Err(anyhow!( "type mismatch: hex address provided for non-address parameter" )), @@ -360,15 +359,15 @@ impl CallDecl { Ok(DynSolValue::Int(x, x.bits() as usize)) } (DynSolType::Int(_), Value::BigInt(i)) => { - let x = abi::I256::from_limbs(i.to_signed_u256().0); + let x = abi::I256::from_le_bytes(i.to_signed_u256().to_le_bytes::<{U256::BYTES}>()); Ok(DynSolValue::Int(x, x.bits() as usize)) } (DynSolType::Uint(_), Value::Int(i)) if *i >= 0 => { - let x = abi::U256::try_from(*i)?; + let x = U256::try_from(*i)?; Ok(DynSolValue::Uint(x, x.bit_len())) } (DynSolType::Uint(_), Value::BigInt(i)) if i.sign() == Sign::Plus => { - let x = abi::U256::from_limbs(i.to_unsigned_u256().0); + let x = i.to_unsigned_u256(); Ok(DynSolValue::Uint(x, x.bit_len())) } (DynSolType::Array(inner_type), Value::List(values)) => { @@ -579,7 +578,7 @@ impl DeclaredCall { pub fn from_log_trigger( mapping: &dyn FindMappingABI, call_decls: &CallDecls, - log: &Log, + log: &alloy::rpc::types::Log, params: &[abi::DynSolParam], ) -> Result, Error> { Self::create_calls(mapping, call_decls, |decl, _| { @@ -643,7 +642,7 @@ impl DeclaredCall { ( ContractCall { contract_name: self.contract_name, - address: alloy::primitives::Address::from(self.address.as_fixed_bytes()), + address: self.address, block_ptr, function: self.function, args: self.args, @@ -728,7 +727,7 @@ mod tests { #[test] fn test_hex_address_call_expr() { let addr = "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF"; - let hex_address = CallArg::HexAddress(web3::types::H160::from_str(addr).unwrap()); + let hex_address = CallArg::HexAddress(Address::from_str(addr).unwrap()); // Test HexAddress in address position let expr: CallExpr = format!("Pool[{}].growth()", addr).parse().unwrap(); diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 1a612cb93e7..6b071f3648f 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -178,8 +178,8 @@ pub mod prelude { pub use crate::util::cache_weight::CacheWeight; pub use crate::util::conversions::{ alloy_address_to_h160, alloy_address_to_web3_address, alloy_log_to_web3_log, - alloy_transaction_receipt_to_web3_transaction_receipt, b256_to_h256, h160_to_alloy_address, - h256_to_b256, web3_address_to_alloy_address, + alloy_transaction_receipt_to_web3_transaction_receipt, h160_to_alloy_address, h256_to_b256, + web3_address_to_alloy_address, }; pub use crate::util::futures::{retry, TimeoutError}; pub use crate::util::stats::MovingStats; diff --git a/graph/src/runtime/mod.rs b/graph/src/runtime/mod.rs index 6732a57429e..15090e5e34a 100644 --- a/graph/src/runtime/mod.rs +++ b/graph/src/runtime/mod.rs @@ -258,7 +258,7 @@ pub enum IndexForAscTypeId { // Reserved discriminant space for more Ethereum type IDs: [1000, 1499] TransactionReceipt = 1000, Log = 1001, - ArrayH256 = 1002, + ArrayB256 = 1002, ArrayLog = 1003, ArrayTypedMapStringStoreValue = 1004, // Continue to add more Ethereum type IDs here. diff --git a/graphql/src/store/resolver.rs b/graphql/src/store/resolver.rs index 8f5eaaccbd1..c770f3efa7a 100644 --- a/graphql/src/store/resolver.rs +++ b/graphql/src/store/resolver.rs @@ -9,6 +9,7 @@ use graph::data::query::{CacheStatus, QueryResults, Trace}; use graph::data::store::ID; use graph::data::value::{Object, Word}; use graph::derive::CheapClone; +use graph::prelude::alloy::primitives::B256; use graph::prelude::*; use graph::schema::{ ast as sast, INTROSPECTION_SCHEMA_FIELD_NAME, INTROSPECTION_TYPE_FIELD_NAME, META_FIELD_NAME, @@ -204,11 +205,11 @@ impl StoreResolver { // locate_block indicates that we do not have a block hash // by setting the hash to `zero` // See 7a7b9708-adb7-4fc2-acec-88680cb07ec1 - let hash_h256 = ptr.hash_as_h256(); - if hash_h256 == web3::types::H256::zero() { + let hash_b256 = ptr.hash_as_b256(); + if hash_b256 == B256::ZERO { None } else { - Some(r::Value::String(format!("0x{:x}", hash_h256))) + Some(r::Value::String(format!("0x{:x}", hash_b256))) } }) .unwrap_or(r::Value::Null); diff --git a/node/src/manager/commands/check_blocks.rs b/node/src/manager/commands/check_blocks.rs index 793a1677c3d..b8061203539 100644 --- a/node/src/manager/commands/check_blocks.rs +++ b/node/src/manager/commands/check_blocks.rs @@ -4,8 +4,8 @@ use graph::{ cheap_clone::CheapClone, components::store::ChainStore as ChainStoreTrait, prelude::{ + alloy::primitives::B256, anyhow::{self, anyhow, Context}, - web3::types::H256, }, slog::Logger, }; @@ -103,7 +103,7 @@ pub fn truncate(chain_store: Arc, skip_confirmation: bool) -> anyhow } async fn run( - block_hash: &H256, + block_hash: &B256, chain_store: Arc, ethereum_adapter: &EthereumAdapter, logger: &Logger, @@ -122,7 +122,7 @@ async fn run( async fn handle_multiple_block_hashes( block_number: i32, - block_hashes: &[H256], + block_hashes: &[B256], chain_store: &ChainStore, delete_duplicates: bool, ) -> anyhow::Result<()> { @@ -156,7 +156,7 @@ mod steps { use graph::{ anyhow::bail, prelude::{ - h256_to_b256, + alloy::primitives::B256, serde_json::{self, Value}, }, }; @@ -170,11 +170,11 @@ mod steps { pub(super) fn resolve_block_hash_from_block_number( number: i32, chain_store: &ChainStore, - ) -> anyhow::Result> { + ) -> anyhow::Result> { let block_hashes = chain_store.block_hashes_by_block_number(number)?; Ok(block_hashes .into_iter() - .map(|x| H256::from_slice(&x.as_slice()[..32])) + .map(|x| B256::from_slice(&x.as_slice()[..32])) .collect()) } @@ -182,7 +182,7 @@ mod steps { /// /// Errors on a non-unary result. pub(super) async fn fetch_single_cached_block( - block_hash: H256, + block_hash: B256, chain_store: Arc, ) -> anyhow::Result { let blocks = chain_store.blocks(vec![block_hash.into()]).await?; @@ -200,18 +200,17 @@ mod steps { /// Errors on provider failure or if the returned block has a different hash than the one /// requested. pub(super) async fn fetch_single_provider_block( - block_hash: &H256, + block_hash: &B256, ethereum_adapter: &EthereumAdapter, logger: &Logger, ) -> anyhow::Result { - let block_hash = h256_to_b256(*block_hash); let provider_block = ethereum_adapter - .block_by_hash(logger, block_hash) + .block_by_hash(logger, *block_hash) .await .with_context(|| format!("failed to fetch block {block_hash}"))? .ok_or_else(|| anyhow!("JRPC provider found no block with hash {block_hash:?}"))?; ensure!( - provider_block.header.hash == block_hash, + provider_block.header.hash == *block_hash, "Provider responded with a different block hash" ); serde_json::to_value(provider_block) @@ -239,7 +238,7 @@ mod steps { } /// Prints the difference between two [`serde_json::Value`] values to the user. - pub(super) fn report_difference(difference: Option<&str>, hash: &H256) { + pub(super) fn report_difference(difference: Option<&str>, hash: &B256) { if let Some(diff) = difference { eprintln!("block {hash} diverges from cache:"); eprintln!("{diff}"); @@ -249,7 +248,7 @@ mod steps { } /// Attempts to delete a block from the block cache. - pub(super) fn delete_block(hash: &H256, chain_store: &ChainStore) -> anyhow::Result<()> { + pub(super) fn delete_block(hash: &B256, chain_store: &ChainStore) -> anyhow::Result<()> { println!("Deleting block {hash} from cache."); chain_store.delete_blocks(&[hash])?; println!("Done."); @@ -265,13 +264,13 @@ mod steps { mod helpers { use super::*; - use graph::prelude::hex; + use graph::prelude::{alloy::primitives::B256, hex}; - /// Tries to parse a [`H256`] from a hex string. - pub(super) fn parse_block_hash(hash: &str) -> anyhow::Result { + /// Tries to parse a [`B256`] from a hex string. + pub(super) fn parse_block_hash(hash: &str) -> anyhow::Result { let hash = hash.trim_start_matches("0x"); let hash = hex::decode(hash)?; - Ok(H256::from_slice(&hash)) + Ok(B256::from_slice(&hash)) } } diff --git a/runtime/test/src/common.rs b/runtime/test/src/common.rs index c2a7d3a231b..ad4469c13ed 100644 --- a/runtime/test/src/common.rs +++ b/runtime/test/src/common.rs @@ -8,6 +8,7 @@ use graph::env::EnvVars; use graph::ipfs::IpfsRpcClient; use graph::ipfs::ServerAddress; use graph::log; +use graph::prelude::alloy::primitives::Address; use graph::prelude::*; use graph_chain_ethereum::{Chain, DataSource, DataSourceTemplate, Mapping, TemplateSource}; use graph_runtime_wasm::host_exports::DataSourceDetails; @@ -15,7 +16,6 @@ use graph_runtime_wasm::{HostExports, MappingContext}; use semver::Version; use std::env; use std::str::FromStr; -use web3::types::Address; lazy_static! { pub static ref LOGGER: Logger = match env::var_os("GRAPH_LOG") { diff --git a/runtime/test/src/test.rs b/runtime/test/src/test.rs index 53a84aec5f1..9e452044828 100644 --- a/runtime/test/src/test.rs +++ b/runtime/test/src/test.rs @@ -5,7 +5,7 @@ use graph::data::store::{scalar, Id, IdType}; use graph::data::subgraph::*; use graph::data::value::Word; use graph::ipfs::test_utils::add_files_to_local_ipfs_node_for_testing; -use graph::prelude::web3::types::U256; +use graph::prelude::alloy::primitives::U256; use graph::runtime::gas::GasCounter; use graph::runtime::{AscIndexId, AscType, HostExportError}; use graph::runtime::{AscPtr, ToAscObj}; @@ -21,7 +21,6 @@ use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; use test_store::{LOGGER, STORE}; use wasmtime::{AsContext, AsContextMut}; -use web3::types::H160; use crate::common::{mock_context, mock_data_source}; @@ -695,19 +694,19 @@ async fn test_big_int_to_hex(api_version: Version, gas_used: u64) { .await; // Convert zero to hex - let zero = BigInt::from_unsigned_u256(&U256::zero()); + let zero = BigInt::from_unsigned_u256(&U256::ZERO); let zero_hex_ptr: AscPtr = instance.invoke_export1("big_int_to_hex", &zero); let zero_hex_str: String = instance.asc_get(zero_hex_ptr).unwrap(); assert_eq!(zero_hex_str, "0x0"); // Convert 1 to hex - let one = BigInt::from_unsigned_u256(&U256::one()); + let one = BigInt::from_unsigned_u256(&U256::ONE); let one_hex_ptr: AscPtr = instance.invoke_export1("big_int_to_hex", &one); let one_hex_str: String = instance.asc_get(one_hex_ptr).unwrap(); assert_eq!(one_hex_str, "0x1"); // Convert U256::max_value() to hex - let u256_max = BigInt::from_unsigned_u256(&U256::max_value()); + let u256_max = BigInt::from_unsigned_u256(&U256::MAX); let u256_max_hex_ptr: AscPtr = instance.invoke_export1("big_int_to_hex", &u256_max); let u256_max_hex_str: String = instance.asc_get(u256_max_hex_ptr).unwrap(); assert_eq!( diff --git a/runtime/test/src/test/abi.rs b/runtime/test/src/test/abi.rs index ac733bad554..47b28288725 100644 --- a/runtime/test/src/test/abi.rs +++ b/runtime/test/src/test/abi.rs @@ -1,5 +1,4 @@ -use graph::abi; -use graph::prelude::web3::types::U256; +use graph::{abi, prelude::alloy::primitives::Address}; use graph_runtime_wasm::asc_abi::class::{ ArrayBuffer, AscAddress, AscEnum, AscEnumArray, EthereumValueKind, StoreValueKind, TypedArray, }; @@ -222,7 +221,7 @@ async fn test_abi_alloy_token_identity(api_version: Version) { assert_eq!(int_token, new_token); // Token::Uint - let uint = abi::U256::from_limbs([256, 453452345, 0, 42]); + let uint = U256::from_limbs([256, 453452345, 0, 42]); let uint_token = abi::DynSolValue::Uint(uint, uint.bit_len()); let new_uint_obj: AscPtr = instance.invoke_export1("token_to_uint", &uint_token); @@ -413,17 +412,17 @@ async fn test_abi_h160(api_version: Version) { api_version, ) .await; - let address = H160::zero(); + let address = Address::ZERO; // As an `Uint8Array` let new_address_obj: AscPtr = module.invoke_export1("test_address", &address); // This should have 1 added to the first and last byte. - let new_address: H160 = module.asc_get(new_address_obj).unwrap(); + let new_address: Address = module.asc_get(new_address_obj).unwrap(); assert_eq!( new_address, - H160([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) + Address::from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) ) } @@ -475,13 +474,13 @@ async fn test_abi_big_int(api_version: Version) { .await; // Test passing in 0 and increment it by 1 - let old_uint = U256::zero(); + let old_uint = U256::ZERO; let new_uint_obj: AscPtr = module.invoke_export1("test_uint", &BigInt::from_unsigned_u256(&old_uint)); let new_uint: BigInt = module.asc_get(new_uint_obj).unwrap(); assert_eq!(new_uint, BigInt::from(1_i32)); let new_uint = new_uint.to_unsigned_u256(); - assert_eq!(new_uint, U256([1, 0, 0, 0])); + assert_eq!(new_uint, U256::from_limbs([1, 0, 0, 0])); // Test passing in -50 and increment it by 1 let old_uint = BigInt::from(-50); diff --git a/runtime/wasm/src/host_exports.rs b/runtime/wasm/src/host_exports.rs index 732deaa221b..122c119bb0f 100644 --- a/runtime/wasm/src/host_exports.rs +++ b/runtime/wasm/src/host_exports.rs @@ -6,10 +6,10 @@ use graph::data::subgraph::API_VERSION_0_0_8; use graph::data::value::Word; use graph::futures03::stream::StreamExt; +use graph::prelude::alloy::primitives::Address; use graph::schema::EntityType; use never::Never; use semver::Version; -use web3::types::H160; use graph::abi; use graph::blockchain::BlockTime; @@ -1146,19 +1146,19 @@ impl HostExports { .map_err(|e| DeterministicHostError::from(Error::from(e))) } - pub(crate) fn string_to_h160( + pub(crate) fn string_to_address( &self, string: &str, gas: &GasCounter, state: &mut BlockState, - ) -> Result { + ) -> Result { Self::track_gas_and_ops( gas, state, gas::DEFAULT_GAS_OP.with_args(complexity::Size, &string), "string_to_h160", )?; - string_to_h160(string) + string_to_address(string) } pub(crate) fn bytes_to_string( @@ -1246,11 +1246,9 @@ impl HostExports { } } -fn string_to_h160(string: &str) -> Result { - // `H160::from_str` takes a hex string with no leading `0x`. - let s = string.trim_start_matches("0x"); - H160::from_str(s) - .with_context(|| format!("Failed to convert string to Address/H160: '{}'", s)) +fn string_to_address(string: &str) -> Result { + Address::from_str(string) + .with_context(|| format!("Failed to convert string to Address: '{}'", string)) .map_err(DeterministicHostError::from) } @@ -1346,8 +1344,8 @@ pub mod test_support { #[test] fn test_string_to_h160_with_0x() { assert_eq!( - H160::from_str("A16081F360e3847006dB660bae1c6d1b2e17eC2A").unwrap(), - string_to_h160("0xA16081F360e3847006dB660bae1c6d1b2e17eC2A").unwrap() + Address::from_str("A16081F360e3847006dB660bae1c6d1b2e17eC2A").unwrap(), + string_to_address("0xA16081F360e3847006dB660bae1c6d1b2e17eC2A").unwrap() ) } diff --git a/runtime/wasm/src/module/context.rs b/runtime/wasm/src/module/context.rs index 03cbf244c23..3324c7afec3 100644 --- a/runtime/wasm/src/module/context.rs +++ b/runtime/wasm/src/module/context.rs @@ -454,7 +454,7 @@ impl WasmInstanceContext<'_> { let s: String = asc_get(self, str_ptr, gas)?; let host_exports = self.as_ref().ctx.host_exports.cheap_clone(); let ctx = &mut self.as_mut().ctx; - let h160 = host_exports.string_to_h160(&s, gas, &mut ctx.state)?; + let h160 = host_exports.string_to_address(&s, gas, &mut ctx.state)?; asc_new(self, &h160, gas) } diff --git a/runtime/wasm/src/to_from/external.rs b/runtime/wasm/src/to_from/external.rs index b8f0d0e61fa..898e9752a01 100644 --- a/runtime/wasm/src/to_from/external.rs +++ b/runtime/wasm/src/to_from/external.rs @@ -1,5 +1,5 @@ -use graph::abi; use graph::abi::DynSolValueExt; +use graph::abi::{self}; use graph::data::store::scalar::Timestamp; use graph::data::value::Word; use graph::prelude::{BigDecimal, BigInt}; @@ -10,7 +10,10 @@ use graph::runtime::{ use graph::{data::store, runtime::DeterministicHostError}; use graph::{prelude::web3::types as web3, runtime::AscHeap}; use graph::{ - prelude::{alloy, serde_json}, + prelude::{ + alloy::{self, primitives::U256}, + serde_json, + }, runtime::FromAscObj, }; use graph_runtime_derive::AscType; @@ -93,27 +96,27 @@ impl FromAscObj for alloy::primitives::B256 { } } -impl FromAscObj for web3::H256 { - fn from_asc_obj( - typed_array: Uint8Array, - heap: &H, - gas: &GasCounter, - depth: usize, - ) -> Result { - let data = <[u8; 32]>::from_asc_obj(typed_array, heap, gas, depth)?; - Ok(Self(data)) - } -} - -impl ToAscObj for web3::H256 { - fn to_asc_obj( - &self, - heap: &mut H, - gas: &GasCounter, - ) -> Result { - self.0.to_asc_obj(heap, gas) - } -} +// impl FromAscObj for web3::H256 { +// fn from_asc_obj( +// typed_array: Uint8Array, +// heap: &H, +// gas: &GasCounter, +// depth: usize, +// ) -> Result { +// let data = <[u8; 32]>::from_asc_obj(typed_array, heap, gas, depth)?; +// Ok(Self(data)) +// } +// } + +// impl ToAscObj for web3::H256 { +// fn to_asc_obj( +// &self, +// heap: &mut H, +// gas: &GasCounter, +// ) -> Result { +// self.0.to_asc_obj(heap, gas) +// } +// } impl ToAscObj for web3::U128 { fn to_asc_obj( @@ -287,14 +290,15 @@ impl FromAscObj> for abi::DynSolValue { EthereumValueKind::Int => { let ptr: AscPtr = AscPtr::from(payload); let n: BigInt = asc_get(heap, ptr, gas, depth)?; - let x = abi::I256::from_limbs(n.to_signed_u256().0); + let x = + abi::I256::from_le_bytes(n.to_signed_u256().to_le_bytes::<{ U256::BYTES }>()); Self::Int(x, x.bits() as usize) } EthereumValueKind::Uint => { let ptr: AscPtr = AscPtr::from(payload); let n: BigInt = asc_get(heap, ptr, gas, depth)?; - let x = abi::U256::from_limbs(n.to_unsigned_u256().0); + let x = U256::from_le_bytes(n.to_unsigned_u256().to_le_bytes::<{ U256::BYTES }>()); Self::Uint(x, x.bit_len()) } diff --git a/server/index-node/src/resolver.rs b/server/index-node/src/resolver.rs index 61a273e353a..c90b80e0f3c 100644 --- a/server/index-node/src/resolver.rs +++ b/server/index-node/src/resolver.rs @@ -3,8 +3,8 @@ use std::convert::TryInto; use graph::data::query::Trace; use graph::data::store::Id; +use graph::prelude::alloy::primitives::Address; use graph::schema::EntityType; -use web3::types::Address; use git_testament::{git_testament, CommitKind}; use graph::blockchain::{Blockchain, BlockchainKind, BlockchainMap}; @@ -363,7 +363,7 @@ impl IndexNodeResolver { if !poi_protection.validate_access_token(self.bearer_token.as_deref()) { // Let's sign the POI with a zero'd address when the access token is // invalid. - indexer = Some(Address::zero()); + indexer = Some(Address::ZERO); } let poi_fut = self diff --git a/store/postgres/src/chain_store.rs b/store/postgres/src/chain_store.rs index 8424ed3daf0..ac72de1dc4a 100644 --- a/store/postgres/src/chain_store.rs +++ b/store/postgres/src/chain_store.rs @@ -9,6 +9,7 @@ use graph::data::store::ethereum::call; use graph::derive::CheapClone; use graph::env::ENV_VARS; use graph::parking_lot::RwLock; +use graph::prelude::alloy::primitives::B256; use graph::prelude::MetricsRegistry; use graph::prometheus::{CounterVec, GaugeVec}; use graph::slog::Logger; @@ -25,7 +26,6 @@ use std::{ use graph::blockchain::{Block, BlockHash, ChainIdentifier, ExtendedBlockPtr}; use graph::cheap_clone::CheapClone; -use graph::prelude::web3::types::{H256, U256}; use graph::prelude::{ async_trait, serde_json as json, transaction_receipt::LightTransactionReceipt, BlockNumber, BlockPtr, CachedEthereumCall, CancelableError, ChainStore as ChainStoreTrait, Error, @@ -55,12 +55,12 @@ impl JsonBlock { } } - fn timestamp(&self) -> Option { + fn timestamp(&self) -> Option { self.data .as_ref() .and_then(|data| data.get("timestamp")) .and_then(|ts| ts.as_str()) - .and_then(|ts| U256::from_dec_str(ts).ok()) + .and_then(|ts| ts.parse::().ok()) } } @@ -100,9 +100,8 @@ mod data { use graph::blockchain::{Block, BlockHash}; use graph::data::store::scalar::Bytes; use graph::internal_error; + use graph::prelude::alloy::primitives::{Address, B256}; use graph::prelude::transaction_receipt::LightTransactionReceipt; - use graph::prelude::web3::types::H160; - use graph::prelude::web3::types::H256; use graph::prelude::{ serde_json as json, BlockNumber, BlockPtr, CachedEthereumCall, Error, StoreError, }; @@ -172,15 +171,15 @@ mod data { // Like H256::from_slice, but returns an error instead of panicking // when `bytes` does not have the right length - fn h256_from_bytes(bytes: &[u8]) -> Result { - if bytes.len() == H256::len_bytes() { - Ok(H256::from_slice(bytes)) + fn b256_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() == B256::len_bytes() { + Ok(B256::from_slice(bytes)) } else { Err(internal_error!( "invalid H256 value `{}` has {} bytes instead of {}", graph::prelude::hex::encode(bytes), bytes.len(), - H256::len_bytes() + B256::len_bytes() )) } } @@ -858,9 +857,9 @@ mod data { conn: &mut PgConnection, chain: &str, first_block: i64, - hash: H256, - genesis: H256, - ) -> Result, Error> { + hash: B256, + genesis: B256, + ) -> Result, Error> { match self { Storage::Shared => { // We recursively build a temp table 'chain' containing the hash and @@ -943,14 +942,14 @@ mod data { ); let missing = sql_query(query) - .bind::(hash.as_bytes()) - .bind::(genesis.as_bytes()) + .bind::(hash.as_slice()) + .bind::(genesis.as_slice()) .bind::(first_block) .load::(conn)?; let missing = match missing.len() { 0 => None, - 1 => Some(h256_from_bytes(&missing[0].hash)?), + 1 => Some(b256_from_bytes(&missing[0].hash)?), _ => { unreachable!("the query can only return no or one row") } @@ -1181,7 +1180,7 @@ mod data { &self, conn: &mut PgConnection, chain: &str, - block_hashes: &[&H256], + block_hashes: &[&B256], ) -> Result { match self { Storage::Shared => { @@ -1206,7 +1205,7 @@ mod data { ); let hashes: Vec<&[u8]> = - block_hashes.iter().map(|hash| hash.as_bytes()).collect(); + block_hashes.iter().map(|hash| hash.as_slice()).collect(); sql_query(query) .bind::, _>(hashes) @@ -1349,7 +1348,7 @@ mod data { .map(|row| CachedEthereumCall { blake3_id: row.0, block_ptr: block_ptr.clone(), - contract_address: H160::from_slice(&row.2[..]), + contract_address: Address::from_slice(&row.2[..]), return_value: row.1, }) .collect()) @@ -1561,7 +1560,7 @@ mod data { pub(crate) fn find_transaction_receipts_in_block( &self, conn: &mut PgConnection, - block_hash: H256, + block_hash: B256, ) -> anyhow::Result> { let query = sql_query(format!( " @@ -1591,7 +1590,7 @@ from ( .bind::(format!("{:x}", block_hash)) .get_results(conn), Storage::Private(_) => query - .bind::(block_hash.as_bytes()) + .bind::(block_hash.as_slice()) .get_results(conn), } }; @@ -1906,7 +1905,7 @@ impl ChainStore { self.recent_blocks_cache.blocks() } - pub fn delete_blocks(&self, block_hashes: &[&H256]) -> Result { + pub fn delete_blocks(&self, block_hashes: &[&B256]) -> Result { let mut conn = self.get_conn()?; self.storage .delete_blocks_by_hash(&mut conn, &self.chain, block_hashes) @@ -1988,7 +1987,7 @@ fn json_block_to_block_ptr_ext(json_block: &JsonBlock) -> Result, ancestor_count: BlockNumber, - ) -> Result, Error> { + ) -> Result, Error> { use public::ethereum_networks as n; let (missing, ptr) = { let chain_store = self.clone(); - let genesis_block_ptr = self.genesis_block_ptr()?.hash_as_h256(); + let genesis_block_ptr = self.genesis_block_ptr()?.hash_as_b256(); self.pool .with_conn(move |conn, _| { let candidate = chain_store @@ -2154,7 +2153,7 @@ impl ChainStoreTrait for ChainStore { conn, &chain_store.chain, first_block as i64, - ptr.hash_as_h256(), + ptr.hash_as_b256(), genesis_block_ptr, ) .map_err(CancelableError::from)? @@ -2169,7 +2168,7 @@ impl ChainStoreTrait for ChainStore { let number = ptr.number as i64; conn.transaction( - |conn| -> Result<(Option, Option<(String, i64)>), StoreError> { + |conn| -> Result<(Option, Option<(String, i64)>), StoreError> { update(n::table.filter(n::name.eq(&chain_store.chain))) .set(( n::head_block_hash.eq(&hash), @@ -2510,7 +2509,7 @@ impl ChainStoreTrait for ChainStore { async fn transaction_receipts_in_block( &self, - block_hash: &H256, + block_hash: &B256, ) -> Result, StoreError> { let pool = self.pool.clone(); let storage = self.storage.clone(); diff --git a/store/postgres/src/deployment.rs b/store/postgres/src/deployment.rs index 4b3da58469d..1f6d9f0b9b1 100644 --- a/store/postgres/src/deployment.rs +++ b/store/postgres/src/deployment.rs @@ -13,6 +13,7 @@ use diesel::{ sql_query, sql_types::{Nullable, Text}, }; +use graph::prelude::alloy::primitives::B256; use graph::{ blockchain::block_stream::FirehoseCursor, data::subgraph::schema::SubgraphError, @@ -23,10 +24,7 @@ use graph::{ use graph::{components::store::StoreResult, semver::Version}; use graph::{ data::store::scalar::ToPrimitive, - prelude::{ - anyhow, hex, web3::types::H256, BlockNumber, BlockPtr, DeploymentHash, DeploymentState, - StoreError, - }, + prelude::{anyhow, hex, BlockNumber, BlockPtr, DeploymentHash, DeploymentState, StoreError}, schema::InputSchema, }; use graph::{ @@ -265,7 +263,7 @@ fn graft( // FIXME: // // workaround for arweave - let hash = H256::from_slice(&hash.as_slice()[..32]); + let hash = B256::from_slice(&hash.as_slice()[..32]); let block = block.to_u64().expect("block numbers fit into a u64"); let subgraph = DeploymentHash::new(subgraph.clone()).map_err(|_| { StoreError::Unknown(anyhow!( @@ -273,7 +271,7 @@ fn graft( subgraph )) })?; - Ok(Some((subgraph, BlockPtr::from((hash, block))))) + Ok(Some((subgraph, BlockPtr::from((hash, block as i32))))) } _ => unreachable!( "graftBlockHash and graftBlockNumber are either both set or neither is set" diff --git a/store/postgres/src/deployment_store.rs b/store/postgres/src/deployment_store.rs index 7aaedf12895..933ae4888a4 100644 --- a/store/postgres/src/deployment_store.rs +++ b/store/postgres/src/deployment_store.rs @@ -18,6 +18,7 @@ use graph::data::subgraph::{status, SPEC_VERSION_0_0_6}; use graph::data_source::CausalityRegion; use graph::derive::CheapClone; use graph::futures03::FutureExt; +use graph::prelude::alloy::primitives::Address; use graph::prelude::{ ApiVersion, CancelHandle, CancelToken, CancelableError, EntityOperation, PoolWaitStats, SubgraphDeploymentEntity, @@ -40,12 +41,11 @@ use graph::components::subgraph::{ProofOfIndexingFinisher, ProofOfIndexingVersio use graph::data::subgraph::schema::{DeploymentCreate, SubgraphError}; use graph::internal_error; use graph::prelude::{ - anyhow, debug, info, o, warn, web3, AttributeNames, BlockNumber, BlockPtr, CheapClone, + anyhow, debug, info, o, warn, AttributeNames, BlockNumber, BlockPtr, CheapClone, DeploymentHash, DeploymentState, Entity, EntityQuery, Error, Logger, QueryExecutionError, StopwatchMetrics, StoreError, UnfailOutcome, Value, ENV_VARS, }; use graph::schema::{ApiSchema, EntityKey, EntityType, InputSchema}; -use web3::types::Address; use crate::block_range::{BLOCK_COLUMN, BLOCK_RANGE_COLUMN}; use crate::deployment::{self, OnSync}; diff --git a/store/postgres/src/detail.rs b/store/postgres/src/detail.rs index 0be3909a2c9..d72f10bd0eb 100644 --- a/store/postgres/src/detail.rs +++ b/store/postgres/src/detail.rs @@ -12,13 +12,14 @@ use git_testament::{git_testament, git_testament_macros}; use graph::blockchain::BlockHash; use graph::data::store::scalar::ToPrimitive; use graph::data::subgraph::schema::{SubgraphError, SubgraphManifestEntity}; +use graph::prelude::alloy::primitives::B256; use graph::prelude::BlockNumber; use graph::prelude::{ chrono::{DateTime, Utc}, BlockPtr, DeploymentHash, StoreError, SubgraphDeploymentEntity, }; use graph::schema::InputSchema; -use graph::{data::subgraph::status, internal_error, prelude::web3::types::H256}; +use graph::{data::subgraph::status, internal_error}; use itertools::Itertools; use std::collections::HashMap; use std::convert::TryFrom; @@ -187,7 +188,7 @@ impl TryFrom for SubgraphError { // FIXME: // // workaround for arweave - let block_hash = block_hash.map(|hash| H256::from_slice(&hash.as_slice()[..32])); + let block_hash = block_hash.map(|hash| B256::from_slice(&hash.as_slice()[..32])); // In existing databases, we have errors that have a `block_range` of // `UNVERSIONED_RANGE`, which leads to `None` as the block number, but // has a hash. Conversely, it is also possible for an error to not have a diff --git a/store/postgres/src/store.rs b/store/postgres/src/store.rs index bda5b2da136..b378d69fecb 100644 --- a/store/postgres/src/store.rs +++ b/store/postgres/src/store.rs @@ -12,8 +12,8 @@ use graph::{ data::subgraph::status, internal_error, prelude::{ - web3::types::Address, BlockNumber, BlockPtr, CheapClone, DeploymentHash, PartialBlockPtr, - QueryExecutionError, StoreError, + alloy::primitives::Address, BlockNumber, BlockPtr, CheapClone, DeploymentHash, + PartialBlockPtr, QueryExecutionError, StoreError, }, }; diff --git a/store/postgres/src/subgraph_store.rs b/store/postgres/src/subgraph_store.rs index 2ba2a1a58f6..4c73b4d0bb4 100644 --- a/store/postgres/src/subgraph_store.rs +++ b/store/postgres/src/subgraph_store.rs @@ -11,7 +11,7 @@ use std::{ }; use std::{iter::FromIterator, time::Duration}; -use graph::futures03::future::join_all; +use graph::{futures03::future::join_all, prelude::alloy::primitives::Address}; use graph::{ cheap_clone::CheapClone, components::{ @@ -25,10 +25,10 @@ use graph::{ data::subgraph::{schema::DeploymentCreate, status, DeploymentFeatures}, internal_error, prelude::{ - anyhow, lazy_static, o, web3::types::Address, ApiVersion, BlockNumber, BlockPtr, - ChainStore, DeploymentHash, EntityOperation, Logger, MetricsRegistry, NodeId, - PartialBlockPtr, StoreError, SubgraphDeploymentEntity, SubgraphName, - SubgraphStore as SubgraphStoreTrait, SubgraphVersionSwitchingMode, + anyhow, lazy_static, o, ApiVersion, BlockNumber, BlockPtr, ChainStore, DeploymentHash, + EntityOperation, Logger, MetricsRegistry, NodeId, PartialBlockPtr, StoreError, + SubgraphDeploymentEntity, SubgraphName, SubgraphStore as SubgraphStoreTrait, + SubgraphVersionSwitchingMode, }, prelude::{CancelableError, StoreEvent}, schema::{ApiSchema, InputSchema}, @@ -1097,7 +1097,7 @@ impl SubgraphStoreInner { }; let block_for_poi_query = BlockPtr::new(block_hash.clone(), block_number); - let indexer = Some(Address::zero()); + let indexer = Some(Address::ZERO); let poi = store .get_proof_of_indexing(site, &indexer, block_for_poi_query) .await?; diff --git a/store/postgres/src/transaction_receipt.rs b/store/postgres/src/transaction_receipt.rs index 115a32f1cc2..73b11c9c400 100644 --- a/store/postgres/src/transaction_receipt.rs +++ b/store/postgres/src/transaction_receipt.rs @@ -39,15 +39,32 @@ impl TryFrom for LightTransactionReceipt { let block_hash = block_hash.map(drain_vector).transpose()?; let block_number = block_number.map(drain_vector).transpose()?; let gas_used = gas_used.map(drain_vector).transpose()?; - let status = status.map(drain_vector).transpose()?; + + // Convert big-endian bytes to numbers + let transaction_index = u64::from_be_bytes(transaction_index); + let block_number = block_number.map(u64::from_be_bytes); + let gas_used = gas_used.map(u64::from_be_bytes).unwrap_or(0); + + // Handle both old U64 format and new boolean format + let status = status + .map(|bytes| { + match bytes.len() { + 1 => bytes[0] != 0, // New format: single byte + 8 => { + u64::from_be_bytes(drain_vector::<8>(bytes.to_vec()).unwrap_or([0; 8])) != 0 + } // Old format: U64 + _ => false, // Fallback + } + }) + .unwrap_or(false); Ok(LightTransactionReceipt { transaction_hash: transaction_hash.into(), - transaction_index: transaction_index.into(), + transaction_index, block_hash: block_hash.map(Into::into), - block_number: block_number.map(Into::into), - gas_used: gas_used.map(Into::into), - status: status.map(Into::into), + block_number, + gas_used, + status, }) } } diff --git a/store/test-store/src/block_store.rs b/store/test-store/src/block_store.rs index 7ac852f8a76..57f8752ab22 100644 --- a/store/test-store/src/block_store.rs +++ b/store/test-store/src/block_store.rs @@ -3,16 +3,13 @@ use std::{convert::TryFrom, str::FromStr, sync::Arc}; use graph::alloy_todo; use graph::blockchain::{BlockTime, ChainIdentifier}; use graph::components::ethereum::BlockWrapper; -use graph::prelude::web3; +use graph::prelude::alloy::primitives::{B256, U256}; use lazy_static::lazy_static; use graph::components::store::BlockStore; use graph::{ blockchain::Block as BlockchainBlock, - prelude::{ - serde_json, web3::types::H256, web3::types::U256, BlockHash, BlockNumber, BlockPtr, - EthereumBlock, - }, + prelude::{serde_json, BlockHash, BlockNumber, BlockPtr, EthereumBlock}, }; use graph_chain_ethereum::codec::{Block as FirehoseBlock, BlockHeader}; use prost_types::Timestamp; @@ -106,7 +103,7 @@ impl FakeBlock { } pub fn as_ethereum_block(&self) -> EthereumBlock { - let parent_hash = H256::from_str(self.parent_hash.as_str()).expect("invalid parent hash"); + let parent_hash = B256::from_str(self.parent_hash.as_str()).expect("invalid parent hash"); // let mut block = web3::types::Block::default(); // block.number = Some(self.number.into()); diff --git a/store/test-store/src/store.rs b/store/test-store/src/store.rs index 96da86a7b64..d4b61f2e56b 100644 --- a/store/test-store/src/store.rs +++ b/store/test-store/src/store.rs @@ -10,6 +10,7 @@ use graph::data::subgraph::schema::{DeploymentCreate, SubgraphError}; use graph::data::subgraph::SubgraphFeature; use graph::data_source::DataSource; use graph::log; +use graph::prelude::alloy::primitives::B256; use graph::prelude::{QueryStoreManager as _, SubgraphStore as _, *}; use graph::schema::EntityType; use graph::schema::InputSchema; @@ -37,7 +38,6 @@ use std::collections::HashMap; use std::time::Instant; use std::{marker::PhantomData, sync::Mutex}; use tokio::runtime::{Builder, Runtime}; -use web3::types::H256; pub const NETWORK_NAME: &str = "fake_network"; pub const DATA_SOURCE_KIND: &str = "mock/kind"; @@ -71,14 +71,14 @@ lazy_static! { pub static ref SUBGRAPH_STORE: Arc = STORE.subgraph_store(); static ref BLOCK_STORE: Arc = STORE.block_store(); pub static ref GENESIS_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "bd34884280958002c51d3f7b5f853e6febeba33de0f40d15b0363006533c924f" )), 0u64 ) .into(); pub static ref BLOCK_ONE: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "8511fa04b64657581e3f00e14543c1d522d5d7e771b54aa3060b662ade47da13" )), 1u64 @@ -86,14 +86,15 @@ lazy_static! { .into(); pub static ref BLOCKS: [BlockPtr; 4] = { let two: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1" )), 2u64, ) .into(); + let three: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "977c084229c72a0fa377cae304eda9099b6a2cb5d83b25cdf0f0969b69874255" )), 3u64, diff --git a/store/test-store/tests/chain/ethereum/manifest.rs b/store/test-store/tests/chain/ethereum/manifest.rs index f025be2e626..f315467319b 100644 --- a/store/test-store/tests/chain/ethereum/manifest.rs +++ b/store/test-store/tests/chain/ethereum/manifest.rs @@ -17,7 +17,7 @@ use graph::data_source::offchain::OffchainDataSourceKind; use graph::data_source::{DataSourceEnum, DataSourceTemplate}; use graph::entity; use graph::env::ENV_VARS; -use graph::prelude::web3::types::H256; +use graph::prelude::alloy::primitives::B256; use graph::prelude::{ anyhow, async_trait, serde_yaml, tokio, BigDecimal, BigInt, DeploymentHash, Link, Logger, SubgraphManifest, SubgraphManifestResolveError, SubgraphManifestValidationError, SubgraphStore, @@ -785,18 +785,18 @@ specVersion: 1.2.0 assert_eq!( Some(vec![ - H256::from_str("0000000000000000000000000000000000000000000000000000000000000000") + B256::from_str("0000000000000000000000000000000000000000000000000000000000000000") .unwrap(), - H256::from_str("0000000000000000000000000000000000000000000000000000000000000001") + B256::from_str("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(), - H256::from_str("0000000000000000000000000000000000000000000000000000000000000002") + B256::from_str("0000000000000000000000000000000000000000000000000000000000000002") .unwrap() ]), topic1.clone() ); assert_eq!( - Some(vec![H256::from_str( + Some(vec![B256::from_str( "0000000000000000000000000000000000000000000000000000000000000001" ) .unwrap()]), @@ -804,7 +804,7 @@ specVersion: 1.2.0 ); assert_eq!( - Some(vec![H256::from_str( + Some(vec![B256::from_str( "0000000000000000000000000000000000000000000000000000000000000002" ) .unwrap()]), diff --git a/store/test-store/tests/graph/entity_cache.rs b/store/test-store/tests/graph/entity_cache.rs index cf9bc3faffa..b9553881c21 100644 --- a/store/test-store/tests/graph/entity_cache.rs +++ b/store/test-store/tests/graph/entity_cache.rs @@ -7,6 +7,7 @@ use graph::components::store::{ use graph::data::store::Id; use graph::data::subgraph::schema::{DeploymentCreate, SubgraphError, SubgraphHealth}; use graph::data_source::CausalityRegion; +use graph::prelude::alloy::primitives::B256; use graph::schema::{EntityKey, EntityType, InputSchema}; use graph::{ components::store::{DeploymentId, DeploymentLocator}, @@ -21,7 +22,6 @@ use slog::Logger; use std::collections::{BTreeMap, BTreeSet}; use std::marker::PhantomData; use std::sync::Arc; -use web3::types::H256; use graph_store_postgres::SubgraphStore as DieselSubgraphStore; use test_store::*; @@ -386,7 +386,7 @@ lazy_static! { InputSchema::parse_latest(ACCOUNT_GQL, LOAD_RELATED_ID.clone()) .expect("Failed to parse user schema"); static ref TEST_BLOCK_1_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "8511fa04b64657581e3f00e14543c1d522d5d7e771b54aa3060b662ade47da13" )), 1u64 diff --git a/store/test-store/tests/postgres/chain_head.rs b/store/test-store/tests/postgres/chain_head.rs index 0d8b92569e2..5eea7196de0 100644 --- a/store/test-store/tests/postgres/chain_head.rs +++ b/store/test-store/tests/postgres/chain_head.rs @@ -6,11 +6,11 @@ use graph::data::store::ethereum::call; use graph::data::store::scalar::Bytes; use graph::env::ENV_VARS; use graph::futures03::executor; +use graph::prelude::alloy::primitives::B256; use std::future::Future; use std::sync::Arc; use graph::cheap_clone::CheapClone; -use graph::prelude::web3::types::H256; use graph::prelude::{alloy, serde_json as json, EthereumBlock}; use graph::prelude::{anyhow::anyhow, anyhow::Error}; use graph::prelude::{BlockNumber, QueryStoreManager, QueryTarget}; @@ -318,7 +318,7 @@ fn check_ancestor( } let act_block = json::from_value::(act.0)?; - let act_hash = format!("{:x}", act_block.block.hash_h256().unwrap()); + let act_hash = format!("{:x}", act_block.block.hash_b256().unwrap()); let exp_hash = &exp.hash; if &act_hash != exp_hash { @@ -498,7 +498,7 @@ fn test_transaction_receipts_in_block_function() { let chain = vec![]; run_test_async(chain, move |store, _, _| async move { let receipts = store - .transaction_receipts_in_block(&H256::zero()) + .transaction_receipts_in_block(&B256::ZERO) .await .unwrap(); assert!(receipts.is_empty()) diff --git a/store/test-store/tests/postgres/relational.rs b/store/test-store/tests/postgres/relational.rs index 5d01bd3c510..248f7a0b7d4 100644 --- a/store/test-store/tests/postgres/relational.rs +++ b/store/test-store/tests/postgres/relational.rs @@ -4,9 +4,10 @@ use diesel::pg::PgConnection; use graph::components::store::write::{EntityModification, RowGroup}; use graph::data::store::scalar; use graph::entity; +use graph::prelude::alloy::primitives::B256; use graph::prelude::{ - o, slog, tokio, web3::types::H256, DeploymentHash, Entity, EntityCollection, EntityFilter, - EntityOrder, EntityQuery, Logger, StopwatchMetrics, Value, ValueType, BLOCK_NUMBER_MAX, + o, slog, tokio, DeploymentHash, Entity, EntityCollection, EntityFilter, EntityOrder, + EntityQuery, Logger, StopwatchMetrics, Value, ValueType, BLOCK_NUMBER_MAX, }; use graph::prelude::{BlockNumber, MetricsRegistry}; use graph::schema::{EntityKey, EntityType, InputSchema}; @@ -185,13 +186,13 @@ lazy_static! { static ref LARGE_INT: BigInt = BigInt::from(std::i64::MAX).pow(17).unwrap(); static ref LARGE_DECIMAL: BigDecimal = BigDecimal::from(1) / BigDecimal::new(LARGE_INT.clone(), 1); - static ref BYTES_VALUE: H256 = H256::from(hex!( + static ref BYTES_VALUE: B256 = B256::from(hex!( "e8b3b02b936c4a4a331ac691ac9a86e197fb7731f14e3108602c87d4dac55160" )); - static ref BYTES_VALUE2: H256 = H256::from(hex!( + static ref BYTES_VALUE2: B256 = B256::from(hex!( "b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1" )); - static ref BYTES_VALUE3: H256 = H256::from(hex!( + static ref BYTES_VALUE3: B256 = B256::from(hex!( "977c084229c72a0fa377cae304eda9099b6a2cb5d83b25cdf0f0969b69874255" )); static ref SCALAR_ENTITY: Entity = { diff --git a/store/test-store/tests/postgres/relational_bytes.rs b/store/test-store/tests/postgres/relational_bytes.rs index 3f4bd88c8d8..bbfcfea7f3e 100644 --- a/store/test-store/tests/postgres/relational_bytes.rs +++ b/store/test-store/tests/postgres/relational_bytes.rs @@ -5,6 +5,7 @@ use graph::components::store::write::RowGroup; use graph::data::store::scalar; use graph::data_source::CausalityRegion; use graph::entity; +use graph::prelude::alloy::primitives::B256; use graph::prelude::{BlockNumber, EntityModification, EntityQuery, MetricsRegistry, StoreError}; use graph::schema::{EntityKey, EntityType, InputSchema}; use hex_literal::hex; @@ -16,9 +17,9 @@ use std::{collections::BTreeMap, sync::Arc}; use graph::data::store::scalar::{BigDecimal, BigInt}; use graph::data::store::IdList; use graph::prelude::{ - o, slog, web3::types::H256, AttributeNames, ChildMultiplicity, DeploymentHash, Entity, - EntityCollection, EntityLink, EntityWindow, Logger, ParentLink, StopwatchMetrics, - WindowAttribute, BLOCK_NUMBER_MAX, + o, slog, AttributeNames, ChildMultiplicity, DeploymentHash, Entity, EntityCollection, + EntityLink, EntityWindow, Logger, ParentLink, StopwatchMetrics, WindowAttribute, + BLOCK_NUMBER_MAX, }; use graph_store_postgres::{ layout_for_tests::make_dummy_site, @@ -45,13 +46,13 @@ lazy_static! { static ref LARGE_INT: BigInt = BigInt::from(std::i64::MAX).pow(17).unwrap(); static ref LARGE_DECIMAL: BigDecimal = BigDecimal::from(1) / BigDecimal::new(LARGE_INT.clone(), 1); - static ref BYTES_VALUE: H256 = H256::from(hex!( + static ref BYTES_VALUE: B256 = B256::from(hex!( "e8b3b02b936c4a4a331ac691ac9a86e197fb7731f14e3108602c87d4dac55160" )); - static ref BYTES_VALUE2: H256 = H256::from(hex!( + static ref BYTES_VALUE2: B256 = B256::from(hex!( "b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1" )); - static ref BYTES_VALUE3: H256 = H256::from(hex!( + static ref BYTES_VALUE3: B256 = B256::from(hex!( "977c084229c72a0fa377cae304eda9099b6a2cb5d83b25cdf0f0969b69874255" )); static ref BEEF_ENTITY: Entity = entity! { THINGS_SCHEMA => diff --git a/store/test-store/tests/postgres/store.rs b/store/test-store/tests/postgres/store.rs index cf9c2bae428..2176de24093 100644 --- a/store/test-store/tests/postgres/store.rs +++ b/store/test-store/tests/postgres/store.rs @@ -3,6 +3,7 @@ use graph::blockchain::BlockTime; use graph::data::graphql::ext::TypeDefinitionExt; use graph::data::subgraph::schema::DeploymentCreate; use graph::data_source::common::MappingABI; +use graph::prelude::alloy::primitives::{Address, B256}; use graph::schema::{EntityType, InputSchema}; use graph_chain_ethereum::Mapping; use hex_literal::hex; @@ -20,7 +21,6 @@ use graph::{data::store::scalar, semver::Version}; use graph::{entity, prelude::*}; use graph_store_postgres::layout_for_tests::STRING_PREFIX_SIZE; use graph_store_postgres::{Store as DieselStore, SubgraphStore as DieselSubgraphStore}; -use web3::types::{Address, H256}; const USER_GQL: &str = " interface ColorAndAge { @@ -64,56 +64,56 @@ lazy_static! { InputSchema::parse_latest(USER_GQL, TEST_SUBGRAPH_ID.clone()) .expect("Failed to parse user schema"); static ref TEST_BLOCK_0_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "bd34884280958002c51d3f7b5f853e6febeba33de0f40d15b0363006533c924f" )), 0u64 ) .into(); static ref TEST_BLOCK_1_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "8511fa04b64657581e3f00e14543c1d522d5d7e771b54aa3060b662ade47da13" )), 1u64 ) .into(); static ref TEST_BLOCK_2_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1" )), 2u64 ) .into(); static ref TEST_BLOCK_3_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "977c084229c72a0fa377cae304eda9099b6a2cb5d83b25cdf0f0969b69874255" )), 3u64 ) .into(); static ref TEST_BLOCK_3A_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "d163aec0592c7cb00c2700ab65dcaac93289f5d250b3b889b39198b07e1fbe4a" )), 3u64 ) .into(); static ref TEST_BLOCK_4_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "007a03cdf635ebb66f5e79ae66cc90ca23d98031665649db056ff9c6aac2d74d" )), 4u64 ) .into(); static ref TEST_BLOCK_4A_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "8fab27e9e9285b0a39110f4d9877f05d0f43d2effa157e55f4dcc49c3cf8cbd7" )), 4u64 ) .into(); static ref TEST_BLOCK_5_PTR: BlockPtr = ( - H256::from(hex!( + B256::from(hex!( "e8b3b02b936c4a4a331ac691ac9a86e197fb7731f14e3108602c87d4dac55160" )), 5u64 diff --git a/store/test-store/tests/postgres/writable.rs b/store/test-store/tests/postgres/writable.rs index d83ec8cbf48..e7ce8fdaa18 100644 --- a/store/test-store/tests/postgres/writable.rs +++ b/store/test-store/tests/postgres/writable.rs @@ -2,6 +2,7 @@ use graph::blockchain::block_stream::{EntitySourceOperation, FirehoseCursor}; use graph::data::subgraph::schema::DeploymentCreate; use graph::data::value::Word; use graph::data_source::CausalityRegion; +use graph::prelude::alloy::primitives::B256; use graph::schema::{EntityKey, EntityType, InputSchema}; use lazy_static::lazy_static; use std::collections::{BTreeMap, BTreeSet}; @@ -17,7 +18,6 @@ use graph::semver::Version; use graph::{entity, prelude::*}; use graph_store_postgres::layout_for_tests::writable; use graph_store_postgres::{Store as DieselStore, SubgraphStore as DieselSubgraphStore}; -use web3::types::H256; const SCHEMA_GQL: &str = " type Counter @entity { @@ -150,7 +150,7 @@ where } fn block_pointer(number: u8) -> BlockPtr { - let hash = H256::from([number; 32]); + let hash = B256::from([number; 32]); BlockPtr::from((hash, number as BlockNumber)) } diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index 8acbcbc49b8..a2b1530b13b 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -6,6 +6,7 @@ use super::{ test_ptr, CommonChainConfig, MutexBlockStreamBuilder, NoopAdapterSelector, NoopRuntimeAdapterBuilder, StaticBlockRefetcher, StaticStreamBuilder, Stores, TestChain, }; +use graph::alloy_todo; use graph::blockchain::block_stream::BlockWithTriggers; use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation}; use graph::blockchain::client::ChainClient; @@ -13,11 +14,9 @@ use graph::blockchain::{BlockPtr, Trigger, TriggersAdapterSelector}; use graph::cheap_clone::CheapClone; use graph::components::ethereum::BlockWrapper; use graph::data_source::subgraph; -use graph::prelude::web3::types::H256; -use graph::prelude::web3::types::{Address, Log, Transaction, H160}; +use graph::prelude::alloy::primitives::{Address, B256, U256}; use graph::prelude::{tiny_keccak, DeploymentHash, Entity, ENV_VARS}; use graph::schema::EntityType; -use graph::{abi, alloy_todo}; use graph_chain_ethereum::network::EthereumNetworkAdapters; use graph_chain_ethereum::trigger::LogRef; use graph_chain_ethereum::Chain; @@ -110,7 +109,7 @@ pub fn generate_empty_blocks_for_range( let parent_ptr = blocks.last().map(|b| b.ptr()).unwrap_or(parent_ptr.clone()); let ptr = BlockPtr { number: i, - hash: H256::from_low_u64_be(i as u64 + add_to_hash).into(), + hash: B256::from(U256::from(i as u64 + add_to_hash)).into(), }; blocks.push(empty_block(parent_ptr, ptr)); } @@ -124,15 +123,15 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers BlockWithTriggers, payload: impl Into) { - let log = Arc::new(Log { - address: Address::zero(), - topics: vec![tiny_keccak::keccak256(b"TestEvent(string)").into()], - data: abi::DynSolValue::String(payload.into()).abi_encode().into(), - block_hash: Some(H256::from_slice(block.ptr().hash.as_slice())), - block_number: Some(block.ptr().number.into()), - transaction_hash: Some(H256::from_low_u64_be(0)), - transaction_index: Some(0.into()), - log_index: Some(0.into()), - transaction_log_index: Some(0.into()), - log_type: None, - removed: None, - }); - block - .trigger_data - .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( - log, None, - )))) + // let log = Arc::new(Log { + // address: Address::ZERO, + // topics: vec![tiny_keccak::keccak256(b"TestEvent(string)").into()], + // data: abi::DynSolValue::String(payload.into()).abi_encode().into(), + // block_hash: Some(B256::from_slice(block.ptr().hash.as_slice())), + // block_number: Some(block.ptr().number.into()), + // transaction_hash: Some(B256::from(U256::from(0))), + // transaction_index: Some(0.into()), + // log_index: Some(0.into()), + // transaction_log_index: Some(0.into()), + // log_type: None, + // removed: None, + // }); + // block + // .trigger_data + // .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( + // log, None, + // )))) + + alloy_todo!() } pub fn push_test_subgraph_trigger( @@ -204,29 +205,31 @@ pub fn push_test_command( test_command: impl Into, data: impl Into, ) { - let log = Arc::new(Log { - address: Address::zero(), - topics: vec![tiny_keccak::keccak256(b"TestEvent(string,string)").into()], - data: abi::DynSolValue::Tuple(vec![ - abi::DynSolValue::String(test_command.into()), - abi::DynSolValue::String(data.into()), - ]) - .abi_encode_params() - .into(), - block_hash: Some(H256::from_slice(block.ptr().hash.as_slice())), - block_number: Some(block.ptr().number.into()), - transaction_hash: Some(H256::from_low_u64_be(0)), - transaction_index: Some(0.into()), - log_index: Some(0.into()), - transaction_log_index: Some(0.into()), - log_type: None, - removed: None, - }); - block - .trigger_data - .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( - log, None, - )))) + // let log = Arc::new(Log { + // address: Address::zero(), + // topics: vec![tiny_keccak::keccak256(b"TestEvent(string,string)").into()], + // data: abi::DynSolValue::Tuple(vec![ + // abi::DynSolValue::String(test_command.into()), + // abi::DynSolValue::String(data.into()), + // ]) + // .abi_encode_params() + // .into(), + // block_hash: Some(B256::from_slice(block.ptr().hash.as_slice())), + // block_number: Some(block.ptr().number.into()), + // transaction_hash: Some(B256::from(U256::from(0))), + // transaction_index: Some(0.into()), + // log_index: Some(0.into()), + // transaction_log_index: Some(0.into()), + // log_type: None, + // removed: None, + // }); + // block + // .trigger_data + // .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( + // log, None, + // )))) + + alloy_todo!() } pub fn push_test_polling_trigger(block: &mut BlockWithTriggers) { diff --git a/tests/src/fixture/mod.rs b/tests/src/fixture/mod.rs index afb34a92eb6..d3e7c0444d2 100644 --- a/tests/src/fixture/mod.rs +++ b/tests/src/fixture/mod.rs @@ -34,8 +34,9 @@ use graph::http_body_util::Full; use graph::hyper::body::Bytes; use graph::hyper::Request; use graph::ipfs::IpfsClient; +use graph::prelude::alloy::primitives::B256; +use graph::prelude::alloy::primitives::U256; use graph::prelude::serde_json::{self, json}; -use graph::prelude::web3::types::H256; use graph::prelude::{ async_trait, lazy_static, q, r, ApiVersion, BigInt, BlockNumber, DeploymentHash, GraphQlRunner as _, IpfsResolver, LoggerFactory, NodeId, QueryError, @@ -72,7 +73,7 @@ pub fn test_ptr(n: BlockNumber) -> BlockPtr { // Set n as the low bits and `reorg_n` as the high bits of the hash. pub fn test_ptr_reorged(n: BlockNumber, reorg_n: u32) -> BlockPtr { - let mut hash = H256::from_low_u64_be(n as u64); + let mut hash = B256::from(U256::from(n as u64)); hash[0..4].copy_from_slice(&reorg_n.to_be_bytes()); BlockPtr { hash: hash.into(), diff --git a/tests/tests/integration_tests.rs b/tests/tests/integration_tests.rs index 4ef1a8b99cf..16aa7041ea4 100644 --- a/tests/tests/integration_tests.rs +++ b/tests/tests/integration_tests.rs @@ -15,8 +15,9 @@ use std::time::{self, Duration, Instant}; use anyhow::{anyhow, bail, Context, Result}; use graph::futures03::StreamExt; +use graph::prelude::alloy::primitives::U256; use graph::prelude::serde_json::{json, Value}; -use graph::prelude::web3::types::U256; +use graph::util::conversions::alloy_u256_to_web3_u256; use graph_tests::contract::Contract; use graph_tests::helpers::{run_checked, TestFile}; use graph_tests::subgraph::Subgraph; @@ -582,9 +583,9 @@ async fn test_topic_filters(ctx: TestContext) -> anyhow::Result<()> { .call( "emitAnotherTrigger", ( - U256::from(1), - U256::from(2), - U256::from(3), + alloy_u256_to_web3_u256(U256::from(1)), + alloy_u256_to_web3_u256(U256::from(2)), + alloy_u256_to_web3_u256(U256::from(3)), "abc".to_string(), ), ) @@ -595,9 +596,9 @@ async fn test_topic_filters(ctx: TestContext) -> anyhow::Result<()> { .call( "emitAnotherTrigger", ( - U256::from(1), - U256::from(1), - U256::from(1), + alloy_u256_to_web3_u256(U256::from(1)), + alloy_u256_to_web3_u256(U256::from(1)), + alloy_u256_to_web3_u256(U256::from(1)), "abc".to_string(), ), ) @@ -608,9 +609,9 @@ async fn test_topic_filters(ctx: TestContext) -> anyhow::Result<()> { .call( "emitAnotherTrigger", ( - U256::from(4), - U256::from(2), - U256::from(3), + alloy_u256_to_web3_u256(U256::from(4)), + alloy_u256_to_web3_u256(U256::from(2)), + alloy_u256_to_web3_u256(U256::from(3)), "abc".to_string(), ), ) @@ -621,9 +622,9 @@ async fn test_topic_filters(ctx: TestContext) -> anyhow::Result<()> { .call( "emitAnotherTrigger", ( - U256::from(4), - U256::from(4), - U256::from(3), + alloy_u256_to_web3_u256(U256::from(4)), + alloy_u256_to_web3_u256(U256::from(4)), + alloy_u256_to_web3_u256(U256::from(3)), "abc".to_string(), ), ) diff --git a/tests/tests/runner_tests.rs b/tests/tests/runner_tests.rs index af828566025..680fb71bf2b 100644 --- a/tests/tests/runner_tests.rs +++ b/tests/tests/runner_tests.rs @@ -16,8 +16,7 @@ use graph::env::{EnvVars, TEST_WITH_NO_REORG}; use graph::ipfs; use graph::ipfs::test_utils::add_files_to_local_ipfs_node_for_testing; use graph::object; -use graph::prelude::web3::types::Address; -use graph::prelude::web3::types::H256; +use graph::prelude::alloy::primitives::{Address, B256, U256}; use graph::prelude::{ hex, CheapClone, DeploymentHash, SubgraphAssignmentProvider, SubgraphName, SubgraphStore, }; @@ -119,7 +118,7 @@ async fn data_source_revert() -> anyhow::Result<()> { let block1 = empty_block(block0.ptr(), test_ptr(1)); let block1_reorged_ptr = BlockPtr { number: 1, - hash: H256::from_low_u64_be(12).into(), + hash: B256::from(U256::from(12)).into(), }; let block1_reorged = empty_block(block0.ptr(), block1_reorged_ptr.clone()); let block2 = empty_block(block1_reorged_ptr, test_ptr(2)); @@ -240,7 +239,7 @@ async fn typename() -> anyhow::Result<()> { let block_1 = empty_block(block_0.ptr(), test_ptr(1)); let block_1_reorged_ptr = BlockPtr { number: 1, - hash: H256::from_low_u64_be(12).into(), + hash: B256::from(U256::from(12)).into(), }; let block_1_reorged = empty_block(block_0.ptr(), block_1_reorged_ptr); let block_2 = empty_block(block_1_reorged.ptr(), test_ptr(2)); @@ -1105,7 +1104,7 @@ async fn retry_create_ds() { let block1 = empty_block(block0.ptr(), test_ptr(1)); let block1_reorged_ptr = BlockPtr { number: 1, - hash: H256::from_low_u64_be(12).into(), + hash: B256::from(U256::from(12)).into(), }; let block1_reorged = empty_block(block0.ptr(), block1_reorged_ptr); let block2 = empty_block(block1_reorged.ptr(), test_ptr(2)); From 924ff9f5b2188f68bfa06cd14ee543d5ed122393 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Sun, 29 Jun 2025 13:44:33 +0530 Subject: [PATCH 41/44] minor refactoring --- chain/ethereum/src/chain.rs | 2 +- chain/ethereum/src/ethereum_adapter.rs | 7 +++--- chain/ethereum/src/trigger.rs | 2 +- chain/near/src/trigger.rs | 4 ++-- graph/src/blockchain/types.rs | 33 ++------------------------ graph/src/components/ethereum/types.rs | 3 +-- graph/src/data_source/common.rs | 3 ++- graphql/src/store/resolver.rs | 2 +- store/postgres/src/chain_store.rs | 4 ++-- store/postgres/src/subgraph_store.rs | 2 +- 10 files changed, 16 insertions(+), 46 deletions(-) diff --git a/chain/ethereum/src/chain.rs b/chain/ethereum/src/chain.rs index c0eb5acb191..5c0aceb301b 100644 --- a/chain/ethereum/src/chain.rs +++ b/chain/ethereum/src/chain.rs @@ -1108,7 +1108,7 @@ impl TriggersAdapterTrait for TriggersAdapter { .load_blocks( self.logger.cheap_clone(), self.chain_store.cheap_clone(), - HashSet::from_iter(Some(block.hash_as_b256())), + HashSet::from_iter(Some(block.hash.as_b256())), ) .await?; assert_eq!(blocks.len(), 1); diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 505385adf9d..a3579b81bca 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -39,7 +39,6 @@ use graph::prelude::{ }, transports::{RpcError, TransportErrorKind}, }, - alloy_log_to_web3_log, h256_to_b256, tokio::try_join, }; use graph::slog::o; @@ -568,7 +567,7 @@ impl EthereumAdapter { if !self.supports_eip_1898 { alloy::rpc::types::BlockId::number(block_ptr.number as u64) } else { - alloy::rpc::types::BlockId::hash(block_ptr.hash_as_b256()) + alloy::rpc::types::BlockId::hash(block_ptr.hash.as_b256()) } } @@ -1692,7 +1691,7 @@ pub(crate) async fn blocks_with_triggers( debug!(logger, "Finding nearest valid `to` block to {}", to); let to_ptr = eth.next_existing_ptr_to_number(&logger, to).await?; - let to_hash = to_ptr.hash_as_b256(); + let to_hash = to_ptr.hash.as_b256(); let to = to_ptr.block_number(); // This is for `start` triggers which can be initialization handlers which needs to be run @@ -2077,7 +2076,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions( // We'll also need the receipts for those transactions. In this step we collect all receipts // we have in store for the current block. let mut receipts: BTreeMap = chain_store - .transaction_receipts_in_block(&block.ptr().hash_as_b256()) + .transaction_receipts_in_block(&block.ptr().hash.as_b256()) .await? .into_iter() .map(|receipt| (receipt.transaction_hash, receipt)) diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index 50a40a74552..f08fe55220c 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -308,7 +308,7 @@ impl EthereumTrigger { pub fn block_hash(&self) -> B256 { match self { - EthereumTrigger::Block(block_ptr, _) => block_ptr.hash_as_b256(), + EthereumTrigger::Block(block_ptr, _) => block_ptr.hash.as_b256(), EthereumTrigger::Call(call) => call.block_hash, EthereumTrigger::Log(log_ref) => log_ref.block_hash().unwrap(), } diff --git a/chain/near/src/trigger.rs b/chain/near/src/trigger.rs index 71b0d46a768..db1aa74ece7 100644 --- a/chain/near/src/trigger.rs +++ b/chain/near/src/trigger.rs @@ -80,8 +80,8 @@ impl NearTrigger { pub fn block_hash(&self) -> B256 { match self { - NearTrigger::Block(block) => block.ptr().hash_as_b256(), - NearTrigger::Receipt(receipt) => receipt.block.ptr().hash_as_b256(), + NearTrigger::Block(block) => block.ptr().hash.as_b256(), + NearTrigger::Receipt(receipt) => receipt.block.ptr().hash.as_b256(), } } diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index d9f428ce28c..48301a77705 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -1,4 +1,4 @@ -use alloy::primitives::{B256, U256}; +use alloy::primitives::B256; use anyhow::anyhow; use diesel::deserialize::FromSql; use diesel::pg::Pg; @@ -178,17 +178,6 @@ impl BlockPtr { self.number } - // // FIXME: - // // - // // workaround for arweave - // pub fn hash_as_h256(&self) -> H256 { - // H256::from_slice(&self.hash_slice()[..32]) - // } - - pub fn hash_as_b256(&self) -> B256 { - B256::from_slice(&self.hash_slice()[..32]) - } - pub fn hash_slice(&self) -> &[u8] { self.hash.0.as_ref() } @@ -268,8 +257,6 @@ impl From<(B256, u64)> for BlockPtr { } } - - impl From<(alloy::primitives::B256, i64)> for BlockPtr { fn from((hash, number): (alloy::primitives::B256, i64)) -> BlockPtr { let number = i32::try_from(number).unwrap(); @@ -341,7 +328,7 @@ impl IntoValue for BlockPtr { impl From for B256 { fn from(ptr: BlockPtr) -> Self { - ptr.hash_as_b256() + ptr.hash.as_b256() } } @@ -425,22 +412,6 @@ impl ExtendedBlockPtr { pub fn block_number(&self) -> BlockNumber { self.number } - - pub fn hash_as_b256(&self) -> B256 { - B256::from_slice(&self.hash_slice()[..32]) - } - - pub fn parent_hash_as_b256(&self) -> B256 { - B256::from_slice(&self.parent_hash_slice()[..32]) - } - - pub fn hash_slice(&self) -> &[u8] { - self.hash.0.as_ref() - } - - pub fn parent_hash_slice(&self) -> &[u8] { - self.parent_hash.0.as_ref() - } } impl fmt::Display for ExtendedBlockPtr { diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index 8a76dd1c7ed..c4e3c9b286c 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -42,8 +42,7 @@ impl BlockWrapper { } pub fn timestamp_u64(&self) -> u64 { - alloy_todo!() - // self.0.timestamp.as_u64() + self.0.header.timestamp } pub fn transactions(&self) -> &[Transaction] { diff --git a/graph/src/data_source/common.rs b/graph/src/data_source/common.rs index 873dc8b41f8..1b8393da4f3 100644 --- a/graph/src/data_source/common.rs +++ b/graph/src/data_source/common.rs @@ -359,7 +359,8 @@ impl CallDecl { Ok(DynSolValue::Int(x, x.bits() as usize)) } (DynSolType::Int(_), Value::BigInt(i)) => { - let x = abi::I256::from_le_bytes(i.to_signed_u256().to_le_bytes::<{U256::BYTES}>()); + let x = + abi::I256::from_le_bytes(i.to_signed_u256().to_le_bytes::<{ U256::BYTES }>()); Ok(DynSolValue::Int(x, x.bits() as usize)) } (DynSolType::Uint(_), Value::Int(i)) if *i >= 0 => { diff --git a/graphql/src/store/resolver.rs b/graphql/src/store/resolver.rs index c770f3efa7a..6b4507c0651 100644 --- a/graphql/src/store/resolver.rs +++ b/graphql/src/store/resolver.rs @@ -205,7 +205,7 @@ impl StoreResolver { // locate_block indicates that we do not have a block hash // by setting the hash to `zero` // See 7a7b9708-adb7-4fc2-acec-88680cb07ec1 - let hash_b256 = ptr.hash_as_b256(); + let hash_b256 = ptr.hash.as_b256(); if hash_b256 == B256::ZERO { None } else { diff --git a/store/postgres/src/chain_store.rs b/store/postgres/src/chain_store.rs index ac72de1dc4a..c37f41e518b 100644 --- a/store/postgres/src/chain_store.rs +++ b/store/postgres/src/chain_store.rs @@ -2135,7 +2135,7 @@ impl ChainStoreTrait for ChainStore { let (missing, ptr) = { let chain_store = self.clone(); - let genesis_block_ptr = self.genesis_block_ptr()?.hash_as_b256(); + let genesis_block_ptr = self.genesis_block_ptr()?.hash.as_b256(); self.pool .with_conn(move |conn, _| { let candidate = chain_store @@ -2153,7 +2153,7 @@ impl ChainStoreTrait for ChainStore { conn, &chain_store.chain, first_block as i64, - ptr.hash_as_b256(), + ptr.hash.as_b256(), genesis_block_ptr, ) .map_err(CancelableError::from)? diff --git a/store/postgres/src/subgraph_store.rs b/store/postgres/src/subgraph_store.rs index 4c73b4d0bb4..e02dc304fa9 100644 --- a/store/postgres/src/subgraph_store.rs +++ b/store/postgres/src/subgraph_store.rs @@ -11,7 +11,6 @@ use std::{ }; use std::{iter::FromIterator, time::Duration}; -use graph::{futures03::future::join_all, prelude::alloy::primitives::Address}; use graph::{ cheap_clone::CheapClone, components::{ @@ -35,6 +34,7 @@ use graph::{ url::Url, util::timed_cache::TimedCache, }; +use graph::{futures03::future::join_all, prelude::alloy::primitives::Address}; use crate::{ deployment::{OnSync, SubgraphHealth}, From f1b9c497cb46009bab71cd0949b584ef5b9c7f8a Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 2 Jul 2025 17:03:06 +0530 Subject: [PATCH 42/44] Fix more todo's, migratye firehose type conversions to alloy instead of web3 --- chain/ethereum/src/adapter.rs | 1 - chain/ethereum/src/chain.rs | 10 - chain/ethereum/src/codec.rs | 669 +++++++++++------- chain/ethereum/src/data_source.rs | 57 +- chain/ethereum/src/ethereum_adapter.rs | 39 +- chain/ethereum/src/runtime/abi.rs | 3 - chain/ethereum/src/tests.rs | 78 +- chain/ethereum/src/trigger.rs | 10 +- graph/src/abi/event_ext.rs | 34 +- graph/src/blockchain/types.rs | 16 +- graph/src/components/ethereum/types.rs | 51 +- graph/src/lib.rs | 6 +- graph/src/util/conversions.rs | 51 +- graph/src/util/mod.rs | 3 + graph/src/util/test_utils.rs | 57 ++ store/test-store/src/block_store.rs | 30 +- store/test-store/tests/postgres/chain_head.rs | 2 +- tests/src/fixture/ethereum.rs | 144 ++-- 18 files changed, 694 insertions(+), 567 deletions(-) create mode 100644 graph/src/util/test_utils.rs diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index dcee5ebd58d..160397dcade 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1324,7 +1324,6 @@ mod tests { #[test] fn ethereum_trigger_filter_to_firehose() { - let address = |value: u64| Address::from_slice(&value.to_le_bytes()); let sig = |value: u64| B256::from_slice(&value.to_le_bytes()); let mut filter = TriggerFilter { log: EthereumLogFilter { diff --git a/chain/ethereum/src/chain.rs b/chain/ethereum/src/chain.rs index 5c0aceb301b..d87d649e22d 100644 --- a/chain/ethereum/src/chain.rs +++ b/chain/ethereum/src/chain.rs @@ -657,16 +657,6 @@ impl BlockFinality { } } -impl<'a> From<&'a BlockFinality> for BlockPtr { - fn from(block: &'a BlockFinality) -> BlockPtr { - match block { - BlockFinality::Final(b) => BlockPtr::from(&**b), - BlockFinality::NonFinal(b) => BlockPtr::from(&b.ethereum_block), - BlockFinality::Ptr(b) => BlockPtr::new(b.hash.clone(), b.number), - } - } -} - impl Block for BlockFinality { fn ptr(&self) -> BlockPtr { match self { diff --git a/chain/ethereum/src/codec.rs b/chain/ethereum/src/codec.rs index bf1e7d85c28..470036d2819 100644 --- a/chain/ethereum/src/codec.rs +++ b/chain/ethereum/src/codec.rs @@ -11,7 +11,12 @@ use graph::{ prelude::{ alloy::{ self, - primitives::{aliases::B2048, Address, Bytes, B256}, + consensus::{ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType}, + primitives::{aliases::B2048, Address, Bloom, Bytes, LogData, B256, U256}, + rpc::types::{ + AccessList, AccessListItem, Block as AlloyBlock, Transaction, + TransactionReceipt as AlloyTransactionReceipt, + }, }, BlockNumber, Error, EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, @@ -51,12 +56,6 @@ impl From<&BigInt> for alloy::primitives::U256 { } } -// impl From<&BigInt> for web3::types::U256 { -// fn from(val: &BigInt) -> Self { -// web3::types::U256::from_big_endian(&val.bytes) -// } -// } - pub struct CallAt<'a> { call: &'a Call, block: &'a Block, @@ -92,41 +91,6 @@ impl<'a> TryInto for CallAt<'a> { } } -// impl TryInto for Call { -// type Error = Error; - -// fn try_into(self) -> Result { -// Ok(web3::types::Call { -// from: self.caller.try_decode_proto("call from address")?, -// to: self.address.try_decode_proto("call to address")?, -// value: self -// .value -// .as_ref() -// .map_or_else(|| U256::from(0), |v| v.into()), -// gas: U256::from(self.gas_limit), -// input: Bytes::from(self.input.clone()), -// call_type: CallType::try_from(self.call_type) -// .map_err(|_| graph::anyhow::anyhow!("invalid call type: {}", self.call_type))? -// .into(), -// }) -// } -// } - -// impl From for web3::types::CallType { -// fn from(val: CallType) -> Self { -// match val { -// CallType::Unspecified => web3::types::CallType::None, -// CallType::Call => web3::types::CallType::Call, -// CallType::Callcode => web3::types::CallType::CallCode, -// CallType::Delegate => web3::types::CallType::DelegateCall, -// CallType::Static => web3::types::CallType::StaticCall, - -// // FIXME (SF): Really not sure what this should map to, we are using None for now, need to revisit -// CallType::Create => web3::types::CallType::None, -// } -// } -// } - pub struct LogAt<'a> { log: &'a Log, block: &'a Block, @@ -139,45 +103,38 @@ impl<'a> LogAt<'a> { } } -// impl<'a> TryInto for LogAt<'a> { -// type Error = Error; - -// fn try_into(self) -> Result { -// Ok(web3::types::Log { -// address: self.log.address.try_decode_proto("log address")?, -// topics: self -// .log -// .topics -// .iter() -// .map(|t| t.try_decode_proto("topic")) -// .collect::, Error>>()?, -// data: Bytes::from(self.log.data.clone()), -// block_hash: Some(self.block.hash.try_decode_proto("log block hash")?), -// block_number: Some(U64::from(self.block.number)), -// transaction_hash: Some(self.trace.hash.try_decode_proto("log transaction hash")?), -// transaction_index: Some(U64::from(self.trace.index as u64)), -// log_index: Some(U256::from(self.log.block_index)), -// transaction_log_index: Some(U256::from(self.log.index)), -// log_type: None, -// removed: None, -// }) -// } -// } - -// impl TryFrom for Option { -// type Error = Error; - -// fn try_from(val: TransactionTraceStatus) -> Result { -// match val { -// TransactionTraceStatus::Unknown => Err(format_err!( -// "Got a transaction trace with status UNKNOWN, datasource is broken" -// )), -// TransactionTraceStatus::Succeeded => Ok(Some(web3::types::U64::from(1))), -// TransactionTraceStatus::Failed => Ok(Some(web3::types::U64::from(0))), -// TransactionTraceStatus::Reverted => Ok(Some(web3::types::U64::from(0))), -// } -// } -// } +impl<'a> TryInto for LogAt<'a> { + type Error = Error; + + fn try_into(self) -> Result { + let topics = self + .log + .topics + .iter() + .map(|t| t.try_decode_proto("topic")) + .collect::, Error>>()?; + + Ok(alloy::rpc::types::Log { + inner: alloy::primitives::Log { + address: self.log.address.try_decode_proto("log address")?, + data: LogData::new(topics, self.log.data.clone().into()) + .ok_or_else(|| format_err!("invalid log data"))?, + }, + block_hash: Some(self.block.hash.try_decode_proto("log block hash")?), + block_number: Some(self.block.number), + transaction_hash: Some(self.trace.hash.try_decode_proto("log transaction hash")?), + transaction_index: Some(self.trace.index as u64), + log_index: Some(self.log.block_index as u64), + removed: false, + block_timestamp: self + .block + .header + .as_ref() + .map(|h| h.timestamp.as_ref().map(|t| t.seconds as u64)) + .flatten(), + }) + } +} pub struct TransactionTraceAt<'a> { trace: &'a TransactionTrace, @@ -190,37 +147,193 @@ impl<'a> TransactionTraceAt<'a> { } } -// impl<'a> TryInto for TransactionTraceAt<'a> { -// type Error = Error; - -// fn try_into(self) -> Result { -// Ok(web3::types::Transaction { -// hash: self.trace.hash.try_decode_proto("transaction hash")?, -// nonce: U256::from(self.trace.nonce), -// block_hash: Some(self.block.hash.try_decode_proto("transaction block hash")?), -// block_number: Some(U64::from(self.block.number)), -// transaction_index: Some(U64::from(self.trace.index as u64)), -// from: Some( -// self.trace -// .from -// .try_decode_proto("transaction from address")?, -// ), -// to: get_to_address(self.trace)?, -// value: self.trace.value.as_ref().map_or(U256::zero(), |x| x.into()), -// gas_price: self.trace.gas_price.as_ref().map(|x| x.into()), -// gas: U256::from(self.trace.gas_limit), -// input: Bytes::from(self.trace.input.clone()), -// v: None, -// r: None, -// s: None, -// raw: None, -// access_list: None, -// max_fee_per_gas: None, -// max_priority_fee_per_gas: None, -// transaction_type: None, -// }) -// } -// } +impl<'a> TryInto for TransactionTraceAt<'a> { + type Error = Error; + + fn try_into(self) -> Result { + use alloy::{ + consensus::transaction::Recovered, + consensus::{ + Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip7702, TxLegacy, + }, + primitives::{Bytes, TxKind, U256}, + rpc::types::Transaction as AlloyTransaction, + }; + + // Extract data from trace and block + let block_hash = self.block.hash.try_decode_proto("transaction block hash")?; + let block_number = self.block.number; + let transaction_index = Some(self.trace.index as u64); + let from_address = self + .trace + .from + .try_decode_proto("transaction from address")?; + let to = get_to_address(self.trace)?; + let value = self.trace.value.as_ref().map_or(U256::ZERO, |x| x.into()); + let gas_price = self.trace.gas_price.as_ref().map_or(0u128, |x| { + let val: U256 = x.into(); + val.to::() + }); + let gas_limit = self.trace.gas_limit; + let input = Bytes::from(self.trace.input.clone()); + + let tx_type = u64::try_from(self.trace.r#type).map_err(|_| { + format_err!( + "Invalid transaction type value {} in transaction trace. Transaction type must be a valid u64.", + self.trace.r#type + ) + })?; + + let tx_type = TxType::try_from(tx_type).map_err(|_| { + format_err!( + "Unsupported transaction type {} in transaction trace. Only standard Ethereum transaction types (Legacy=0, EIP-2930=1, EIP-1559=2, EIP-4844=3, EIP-7702=4) are supported.", + tx_type + ) + })?; + + let nonce = self.trace.nonce; + + // Extract EIP-1559 fee fields from trace + let max_fee_per_gas_u128 = self.trace.max_fee_per_gas.as_ref().map_or(gas_price, |x| { + let val: U256 = x.into(); + val.to::() + }); + + let max_priority_fee_per_gas_u128 = + self.trace + .max_priority_fee_per_gas + .as_ref() + .map_or(0u128, |x| { + let val: U256 = x.into(); + val.to::() + }); + + // Extract access list from trace + let access_list: AccessList = self + .trace + .access_list + .iter() + .map(|access_tuple| { + let address = Address::from_slice(&access_tuple.address); + let storage_keys = access_tuple + .storage_keys + .iter() + .map(|key| B256::from_slice(key)) + .collect(); + AccessListItem { + address, + storage_keys, + } + }) + .collect::>() + .into(); + + // Extract actual signature components from trace + let signature = extract_signature_from_trace(self.trace, tx_type)?; + + let to_kind = match to { + Some(addr) => TxKind::Call(addr), + None => TxKind::Create, + }; + + let envelope = match tx_type { + TxType::Legacy => { + let tx = TxLegacy { + chain_id: None, + nonce, + gas_price, + gas_limit, + to: to_kind, + value, + input: input.clone(), + }; + let signed_tx = Signed::new_unchecked(tx, signature, B256::ZERO); // TODO(alloy_migration): extract actual transaction hash from trace + TxEnvelope::Legacy(signed_tx) + } + TxType::Eip2930 => { + let tx = TxEip2930 { + chain_id: 1, // TODO(alloy_migration): extract actual chain_id from trace + nonce, + gas_price, + gas_limit, + to: to_kind, + value, + access_list: access_list.clone(), // Use actual access list from trace + input: input.clone(), + }; + let signed_tx = Signed::new_unchecked(tx, signature, B256::ZERO); // TODO(alloy_migration): extract actual transaction hash from trace + TxEnvelope::Eip2930(signed_tx) + } + TxType::Eip1559 => { + let tx = TxEip1559 { + chain_id: 1, // TODO(alloy_migration): extract actual chain_id from trace + nonce, + gas_limit, + max_fee_per_gas: max_fee_per_gas_u128, + max_priority_fee_per_gas: max_priority_fee_per_gas_u128, + to: to_kind, + value, + access_list: access_list.clone(), // Use actual access list from trace + input: input.clone(), + }; + let signed_tx = Signed::new_unchecked(tx, signature, B256::ZERO); // TODO(alloy_migration): extract actual transaction hash from trace + TxEnvelope::Eip1559(signed_tx) + } + TxType::Eip4844 => { + let to_address = to.ok_or_else(|| { + format_err!("EIP-4844 transactions cannot be contract creation transactions. The 'to' field must contain a valid address.") + })?; + + let tx_eip4844 = TxEip4844 { + chain_id: 1, // TODO(alloy_migration): extract actual chain_id from trace + nonce, + gas_limit, + max_fee_per_gas: max_fee_per_gas_u128, + max_priority_fee_per_gas: max_priority_fee_per_gas_u128, + to: to_address, + value, + access_list: access_list.clone(), // Use actual access list from trace + blob_versioned_hashes: Vec::new(), // TODO(alloy_migration): extract actual blob hashes from trace + max_fee_per_blob_gas: 0u128, // TODO(alloy_migration): extract actual blob gas fee from trace + input: input.clone(), + }; + let tx = TxEip4844Variant::TxEip4844(tx_eip4844); + let signed_tx = Signed::new_unchecked(tx, signature, B256::ZERO); // TODO(alloy_migration): extract actual transaction hash from trace + TxEnvelope::Eip4844(signed_tx) + } + TxType::Eip7702 => { + let to_address = to.ok_or_else(|| { + format_err!("EIP-7702 transactions cannot be contract creation transactions. The 'to' field must contain a valid address.") + })?; + + let tx = TxEip7702 { + chain_id: 1, // TODO(alloy_migration): extract actual chain_id from trace + nonce, + gas_limit, + max_fee_per_gas: max_fee_per_gas_u128, + max_priority_fee_per_gas: max_priority_fee_per_gas_u128, + to: to_address, + value, + access_list: access_list.clone(), // Use actual access list from trace + authorization_list: Vec::new(), // TODO(alloy_migration): extract actual authorization list from trace + input: input.clone(), + }; + let signed_tx = Signed::new_unchecked(tx, signature, B256::ZERO); // TODO(alloy_migration): extract actual transaction hash from trace + TxEnvelope::Eip7702(signed_tx) + } + }; + + let recovered = Recovered::new_unchecked(envelope, from_address); + + Ok(AlloyTransaction { + inner: recovered, + block_hash: Some(block_hash), + block_number: Some(block_number), + transaction_index, + effective_gas_price: if gas_price > 0 { Some(gas_price) } else { None }, // TODO(alloy_migration): calculate actual effective gas price from trace + }) + } +} impl TryInto for &Block { type Error = Error; @@ -230,147 +343,100 @@ impl TryInto for &Block { } } +impl TryInto for &Block { + type Error = Error; + + fn try_into(self) -> Result { + let header = self.header(); + + let block_hash = self.hash.try_decode_proto("block hash")?; + let consensus_header = alloy::consensus::Header { + number: header.number, + beneficiary: header.coinbase.try_decode_proto("author / coinbase")?, + parent_hash: header.parent_hash.try_decode_proto("parent hash")?, + ommers_hash: header.uncle_hash.try_decode_proto("uncle hash")?, + state_root: header.state_root.try_decode_proto("state root")?, + transactions_root: header + .transactions_root + .try_decode_proto("transactions root")?, + receipts_root: header.receipt_root.try_decode_proto("receipt root")?, + gas_used: header.gas_used, + gas_limit: header.gas_limit, + base_fee_per_gas: header.base_fee_per_gas.as_ref().map(|v| { + let val: U256 = v.into(); + val.to::() + }), + extra_data: Bytes::from(header.extra_data.clone()), + logs_bloom: if header.logs_bloom.is_empty() { + Bloom::ZERO + } else { + Bloom::try_from(header.logs_bloom.as_slice())? + }, + timestamp: header.timestamp.as_ref().map_or(0, |v| v.seconds as u64), + difficulty: header + .difficulty + .as_ref() + .map_or_else(|| U256::ZERO, |v| v.into()), + + mix_hash: header.mix_hash.try_decode_proto("mix hash")?, + nonce: header.nonce.into(), + + withdrawals_root: None, // TODO(alloy_migration): extract from header if available + blob_gas_used: None, // TODO(alloy_migration): extract from header if available + excess_blob_gas: None, // TODO(alloy_migration): extract from header if available + parent_beacon_block_root: None, // TODO(alloy_migration): extract from header if available + requests_hash: None, // TODO(alloy_migration): extract from header if available + }; + + let rpc_header = alloy::rpc::types::Header { + hash: block_hash, + inner: consensus_header, + total_difficulty: header.total_difficulty.as_ref().map(|v| v.into()), + size: Some(U256::from(self.size)), + }; + + let transactions = self + .transaction_traces + .iter() + .map(|t| TransactionTraceAt::new(t, self).try_into()) + .collect::, Error>>()?; + + let uncles = self + .uncles + .iter() + .map(|u| u.hash.try_decode_proto("uncle hash")) + .collect::, _>>()?; + + Ok(AlloyBlock::new( + rpc_header, + alloy::rpc::types::BlockTransactions::Full(transactions), + ) + .with_uncles(uncles)) + } +} + impl TryInto for &Block { type Error = Error; fn try_into(self) -> Result { - let header = self.header.as_ref().ok_or_else(|| { - format_err!("block header should always be present from gRPC Firehose") - })?; - - // let web3_block = web3::types::Block { - // hash: Some(self.hash.try_decode_proto("block hash")?), - // number: Some(U64::from(self.number)), - // author: header.coinbase.try_decode_proto("author / coinbase")?, - // parent_hash: header.parent_hash.try_decode_proto("parent hash")?, - // uncles_hash: header.uncle_hash.try_decode_proto("uncle hash")?, - // state_root: header.state_root.try_decode_proto("state root")?, - // transactions_root: header - // .transactions_root - // .try_decode_proto("transactions root")?, - // receipts_root: header.receipt_root.try_decode_proto("receipt root")?, - // gas_used: U256::from(header.gas_used), - // gas_limit: U256::from(header.gas_limit), - // base_fee_per_gas: Some( - // header - // .base_fee_per_gas - // .as_ref() - // .map_or_else(U256::default, |v| v.into()), - // ), - // extra_data: Bytes::from(header.extra_data.clone()), - // logs_bloom: match &header.logs_bloom.len() { - // 0 => None, - // _ => Some(header.logs_bloom.try_decode_proto("logs bloom")?), - // }, - // timestamp: header - // .timestamp - // .as_ref() - // .map_or_else(U256::default, |v| U256::from(v.seconds)), - // difficulty: header - // .difficulty - // .as_ref() - // .map_or_else(U256::default, |v| v.into()), - // total_difficulty: Some( - // header - // .total_difficulty - // .as_ref() - // .map_or_else(U256::default, |v| v.into()), - // ), - // // FIXME (SF): Firehose does not have seal fields, are they really used? Might be required for POA chains only also, I've seen that stuff on xDai (is this important?) - // seal_fields: vec![], - // uncles: self - // .uncles - // .iter() - // .map(|u| u.hash.try_decode_proto("uncle hash")) - // .collect::, _>>()?, - // transactions: self - // .transaction_traces - // .iter() - // .map(|t| TransactionTraceAt::new(t, self).try_into()) - // .collect::, Error>>()?, - // size: Some(U256::from(self.size)), - // mix_hash: Some(header.mix_hash.try_decode_proto("mix hash")?), - // nonce: Some(H64::from_low_u64_be(header.nonce)), - // }; + let alloy_block: AlloyBlock = self.try_into()?; + + let transaction_receipts = self + .transaction_traces + .iter() + .filter_map(|t| transaction_trace_to_alloy_txn_reciept(t, self).transpose()) + .collect::, Error>>()? + .into_iter() + // Transaction receipts will be shared along the code, so we put them into an + // Arc here to avoid excessive cloning. + .map(Arc::new) + .collect(); #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(LightEthereumBlock::new(alloy_todo!())), - transaction_receipts: self - .transaction_traces - .iter() - .filter_map(|t| { - t.receipt.as_ref().map(|r| { - // Ok(web3::types::TransactionReceipt { - // transaction_hash: t.hash.try_decode_proto("transaction hash")?, - // transaction_index: U64::from(t.index), - // block_hash: Some( - // self.hash.try_decode_proto("transaction block hash")?, - // ), - // block_number: Some(U64::from(self.number)), - // cumulative_gas_used: U256::from(r.cumulative_gas_used), - // // FIXME (SF): What is the rule here about gas_used being None, when it's 0? - // gas_used: Some(U256::from(t.gas_used)), - // contract_address: { - // match t.calls.len() { - // 0 => None, - // _ => { - // match CallType::try_from(t.calls[0].call_type).map_err( - // |_| { - // graph::anyhow::anyhow!( - // "invalid call type: {}", - // t.calls[0].call_type, - // ) - // }, - // )? { - // CallType::Create => { - // Some(t.calls[0].address.try_decode_proto( - // "transaction contract address", - // )?) - // } - // _ => None, - // } - // } - // } - // }, - // logs: r - // .logs - // .iter() - // .map(|l| LogAt::new(l, self, t).try_into()) - // .collect::, Error>>()?, - // status: TransactionTraceStatus::try_from(t.status) - // .map_err(|_| { - // graph::anyhow::anyhow!( - // "invalid transaction trace status: {}", - // t.status - // ) - // })? - // .try_into()?, - // root: match r.state_root.len() { - // 0 => None, // FIXME (SF): should this instead map to [0;32]? - // // FIXME (SF): if len < 32, what do we do? - // _ => Some( - // r.state_root.try_decode_proto("transaction state root")?, - // ), - // }, - // logs_bloom: r - // .logs_bloom - // .try_decode_proto("transaction logs bloom")?, - // from: t.from.try_decode_proto("transaction from")?, - // to: get_to_address(t)?, - // transaction_type: None, - // effective_gas_price: None, - // }) - Ok(alloy_todo!()) - }) - }) - .collect::, Error>>()? - .into_iter() - // Transaction receipts will be shared along the code, so we put them into an - // Arc here to avoid excessive cloning. - .map(Arc::new) - .collect(), + block: Arc::new(LightEthereumBlock::new(alloy_block)), + transaction_receipts, }, // Comment (437a9f17-67cc-478f-80a3-804fe554b227): This Some() will avoid calls in the triggers_in_block // TODO: Refactor in a way that this is no longer needed. @@ -393,6 +459,112 @@ impl TryInto for &Block { } } +fn transaction_trace_to_alloy_txn_reciept( + t: &TransactionTrace, + block: &Block, +) -> Result>>, Error> { + use alloy::consensus::{Eip658Value, Receipt}; + let r = t.receipt.as_ref(); + + if r.is_none() { + return Ok(None); + } + + let r = r.unwrap(); + + let contract_address = match t.calls.len() { + 0 => None, + _ => { + match CallType::try_from(t.calls[0].call_type).map_err(|_| { + graph::anyhow::anyhow!("invalid call type: {}", t.calls[0].call_type) + })? { + CallType::Create => Some( + t.calls[0] + .address + .try_decode_proto("transaction contract address")?, + ), + _ => None, + } + } + }; + + let state_root = match &r.state_root { + b if b.is_empty() => None, + _ => Some(r.state_root.try_decode_proto("transaction state root")?), + }; + + let status = match TransactionTraceStatus::try_from(t.status) + .map_err(|_| format_err!("invalid transaction trace status: {}", t.status))? + { + TransactionTraceStatus::Unknown => { + return Err(format_err!( + "Transaction trace has UNKNOWN status; datasource is broken" + )) + } + TransactionTraceStatus::Succeeded => true, + TransactionTraceStatus::Failed | TransactionTraceStatus::Reverted => false, + }; + + // [EIP-658]: https://eips.ethereum.org/EIPS/eip-658 + // Before EIP-658, the state root field was used to indicate the status of the transaction. + // After EIP-658, the status field is used to indicate the status of the transaction. + let status = match state_root { + Some(root) => Eip658Value::PostState(root), + None => Eip658Value::Eip658(status), + }; + + let logs: Vec = r + .logs + .iter() + .map(|l| LogAt::new(l, block, t).try_into()) + .collect::, Error>>()?; + + let core_receipt = Receipt { + status, + cumulative_gas_used: r.cumulative_gas_used, + logs, + }; + + let logs_bloom = Bloom::try_from(r.logs_bloom.as_slice())?; + + let receipt_with_bloom = ReceiptWithBloom::new(core_receipt, logs_bloom); + + let tx_type = TxType::try_from(u64::try_from(t.r#type).map_err(|_| { + format_err!( + "Invalid transaction type value {} in transaction receipt. Transaction type must be a valid u64.", + t.r#type + ) + })?).map_err(|_| { + format_err!( + "Unsupported transaction type {} in transaction receipt. Only standard Ethereum transaction types (Legacy=0, EIP-2930=1, EIP-1559=2, EIP-4844=3, EIP-7702=4) are supported.", + t.r#type + ) + })?; + + let envelope = match tx_type { + TxType::Legacy => ReceiptEnvelope::Legacy(receipt_with_bloom), + TxType::Eip2930 => ReceiptEnvelope::Eip2930(receipt_with_bloom), + TxType::Eip1559 => ReceiptEnvelope::Eip1559(receipt_with_bloom), + TxType::Eip4844 => ReceiptEnvelope::Eip4844(receipt_with_bloom), + TxType::Eip7702 => ReceiptEnvelope::Eip7702(receipt_with_bloom), + }; + + Ok(Some(AlloyTransactionReceipt { + transaction_hash: t.hash.try_decode_proto("transaction hash")?, + transaction_index: Some(t.index as u64), + block_hash: Some(block.hash.try_decode_proto("transaction block hash")?), + block_number: Some(block.number), + gas_used: t.gas_used, + contract_address, + from: t.from.try_decode_proto("transaction from")?, + to: get_to_address(t)?, + effective_gas_price: 0, // TODO(alloy_migration): calculate actual effective gas price from trace + blob_gas_used: None, // TODO(alloy_migration): extract blob gas used from trace if applicable + blob_gas_price: None, // TODO(alloy_migration): extract blob gas price from trace if applicable + inner: envelope, + })) +} + impl BlockHeader { pub fn parent_ptr(&self) -> Option { match self.parent_hash.len() { @@ -547,6 +719,13 @@ mod test { } } +fn extract_signature_from_trace( + _trace: &TransactionTrace, + _tx_type: TxType, +) -> Result { + alloy_todo!() +} + fn get_to_address(trace: &TransactionTrace) -> Result, Error> { // Try to detect contract creation transactions, which have no 'to' address let is_contract_creation = trace.to.len() == 0 diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index aed4af76055..f24f0c931ed 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Error}; use anyhow::{ensure, Context}; +use graph::abi; use graph::abi::EventExt; use graph::abi::FunctionExt; use graph::blockchain::{BlockPtr, TriggerWithHandler}; @@ -15,11 +16,13 @@ use graph::env::ENV_VARS; use graph::futures03::future::try_join; use graph::futures03::stream::FuturesOrdered; use graph::futures03::TryStreamExt; -use graph::prelude::alloy::primitives::{Address, B256}; -use graph::prelude::alloy::rpc::types::Log; +use graph::prelude::alloy::{ + consensus::{TxEnvelope, TxLegacy}, + primitives::{Address, B256}, + rpc::types::{Log, Transaction}, +}; use graph::prelude::{alloy, Link, SubgraphManifestValidationError}; use graph::slog::{debug, error, o, trace}; -use graph::{abi, alloy_todo}; use itertools::Itertools; use serde::de::Error as ErrorD; use serde::{Deserialize, Deserializer}; @@ -428,6 +431,39 @@ impl blockchain::DataSource for DataSource { } } +/// Generic function that creates a mock legacy Transaction from ANY log +fn create_dummy_transaction( + block_number: u64, + block_hash: B256, + transaction_index: Option, + transaction_hash: Option, +) -> Result, anyhow::Error> { + use graph::prelude::alloy::{ + consensus::transaction::Recovered, + consensus::Signed, + primitives::{Signature, U256}, + }; + + let tx = TxLegacy::default(); + + // Create a dummy signature + let signature = Signature::new(U256::ZERO, U256::ZERO, false); + + let tx_hash = transaction_hash.ok_or(anyhow!("Log has no transaction hash"))?; + let signed_tx = Signed::new_unchecked(tx, signature, tx_hash); + let envelope = TxEnvelope::Legacy(signed_tx); + + let recovered = Recovered::new_unchecked(envelope, Address::ZERO); + + Ok(Transaction { + inner: recovered, + block_hash: Some(block_hash), + block_number: Some(block_number), + transaction_index: transaction_index, + effective_gas_price: None, + }) +} + impl DataSource { fn from_manifest( kind: String, @@ -748,15 +784,12 @@ impl DataSource { let transaction = if log.transaction_hash == Some(block.hash()) || log.transaction_hash == Some(B256::ZERO) { - // Transaction { - // hash: log.transaction_hash.unwrap(), - // block_hash: block.hash_h256(), - // block_number: block.number_web3_u64(), - // transaction_index: log.transaction_index, - // from: Some(H160::zero()), - // ..Transaction::default() - // } - alloy_todo!() + create_dummy_transaction( + block.number_u64(), + block.hash(), + log.transaction_index, + log.transaction_hash, + )? } else { // This is the general case where the log's transaction hash does not match the block's hash // and is not a special zero hash, implying a real transaction associated with this log. diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index a3579b81bca..9a654196615 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -2,6 +2,7 @@ use futures03::{future::BoxFuture, stream::FuturesUnordered}; use graph::abi; use graph::abi::DynSolValueExt; use graph::abi::FunctionExt; +use graph::alloy_todo; use graph::blockchain::client::ChainClient; use graph::blockchain::BlockHash; use graph::blockchain::ChainIdentifier; @@ -152,8 +153,8 @@ impl EthereumAdapter { provider: _, url: rpc_url, } => rpc_url.clone(), - Transport::IPC(_ipc) => todo!(), - Transport::WS(_web_socket) => todo!(), + Transport::IPC(_ipc) => alloy_todo!(), + Transport::WS(_web_socket) => alloy_todo!(), }; let web3 = Arc::new(Web3::new(transport)); let alloy = Arc::new( @@ -1937,7 +1938,7 @@ pub(crate) fn parse_block_triggers( return vec![]; } - let block_ptr = BlockPtr::from(&block.ethereum_block); + let block_ptr = block.ethereum_block.block.block_ptr(); let trigger_every_block = block_filter.trigger_every_block; let call_filter = EthereumCallFilter::from(block_filter); let block_ptr2 = block_ptr.cheap_clone(); @@ -2610,14 +2611,13 @@ mod tests { check_block_receipt_support, parse_block_triggers, EthereumBlock, EthereumBlockFilter, EthereumBlockWithCalls, }; - use graph::alloy_todo; use graph::blockchain::BlockPtr; use graph::components::ethereum::BlockWrapper; use graph::prelude::alloy::primitives::{Address, Bytes, B256}; use graph::prelude::alloy::providers::mock::Asserter; use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; - use graph::prelude::EthereumCall; + use graph::prelude::{create_minimal_block_for_test, EthereumCall}; use jsonrpc_core::serde_json::{self, Value}; use std::collections::HashSet; use std::iter::FromIterator; @@ -2625,17 +2625,12 @@ mod tests { #[test] fn parse_block_triggers_every_block() { - // let web3_block = Web3Block { - // hash: Some(hash(2)), - // number: Some(U64::from(2)), - // ..Default::default() - // }; - let web3_block = alloy_todo!(); + let block = create_minimal_block_for_test(2, hash(2)); #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(web3_block)), + block: Arc::new(BlockWrapper::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2772,17 +2767,12 @@ mod tests { #[test] fn parse_block_triggers_specific_call_not_found() { - // let web3_block = Web3Block { - // hash: Some(hash(2)), - // number: Some(U64::from(2)), - // ..Default::default() - // }; - let web3_block = alloy_todo!(); + let block = create_minimal_block_for_test(2, hash(2)); #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(web3_block)), + block: Arc::new(BlockWrapper::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2808,17 +2798,12 @@ mod tests { #[test] fn parse_block_triggers_specific_call_found() { - // let web3_block = Web3Block { - // hash: Some(hash(2)), - // number: Some(U64::from(2)), - // ..Default::default() - // }; - let web3_block = alloy_todo!(); + let block = create_minimal_block_for_test(2, hash(2)); #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(web3_block)), + block: Arc::new(BlockWrapper::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2846,7 +2831,7 @@ mod tests { } fn address(id: u64) -> Address { - Address::from_slice(&id.to_le_bytes()) + Address::left_padding_from(&id.to_be_bytes()) } fn hash(id: u8) -> B256 { diff --git a/chain/ethereum/src/runtime/abi.rs b/chain/ethereum/src/runtime/abi.rs index c1af6b93feb..f20182cbca6 100644 --- a/chain/ethereum/src/runtime/abi.rs +++ b/chain/ethereum/src/runtime/abi.rs @@ -6,7 +6,6 @@ use anyhow::anyhow; use graph::abi; use graph::prelude::alloy; use graph::prelude::alloy::network::ReceiptResponse; -use graph::prelude::alloy::primitives::B256; use graph::prelude::alloy::rpc::types::{Log, TransactionReceipt}; use graph::{ prelude::BigInt, @@ -553,8 +552,6 @@ impl<'a> ToAscObj for EthereumTransactionData<'a> heap: &mut H, gas: &GasCounter, ) -> Result { - let value = self.value(); - Ok(AscEthereumTransaction_0_0_6 { hash: asc_new(heap, self.hash(), gas)?, index: asc_new(heap, &BigInt::from(self.index()), gas)?, diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index 6d22bc97bc4..94cf007d531 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -1,13 +1,13 @@ use std::sync::Arc; use graph::{ - alloy_todo, blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger}, components::ethereum::BlockWrapper, prelude::{ alloy::{ - primitives::{Address, Bytes, B256}, - rpc::types::Log, + self, + primitives::{Address, Bytes, LogData, B256}, + rpc::types::{Block, Log}, }, rand::{self, Rng}, EthereumCall, @@ -42,6 +42,24 @@ impl Random for Address { } } +fn create_log(tx_index: u64, log_index: u64) -> Arc { + let log = Log { + inner: alloy::primitives::Log { + address: Address::default(), + data: LogData::new_unchecked(vec![], Bytes::from(vec![])), + }, + block_hash: Some(B256::ZERO), + block_number: Some(0), + block_timestamp: Some(0), + transaction_hash: Some(B256::ZERO), + transaction_index: Some(tx_index), + log_index: Some(log_index), + removed: false, + }; + + Arc::new(log) +} + #[test] fn test_trigger_ordering() { let block1 = EthereumTrigger::Block( @@ -74,23 +92,6 @@ fn test_trigger_ordering() { call4.input = Bytes::from(vec![1]); let call4 = EthereumTrigger::Call(Arc::new(call4)); - fn create_log(tx_index: u64, log_index: u64) -> Arc { - // Arc::new(Log { - // address: H160::default(), - // topics: vec![], - // data: Bytes::default(), - // block_hash: Some(H256::zero()), - // block_number: Some(U64::zero()), - // transaction_hash: Some(H256::zero()), - // transaction_index: Some(tx_index.into()), - // log_index: Some(log_index.into()), - // transaction_log_index: Some(log_index.into()), - // log_type: Some("".into()), - // removed: Some(false), - // }) - alloy_todo!() - } - // Event with transaction_index 1 and log_index 0; // should be the first element after sorting let log1 = EthereumTrigger::Log(LogRef::FullLog(create_log(1, 0), None)); @@ -121,16 +122,8 @@ fn test_trigger_ordering() { let logger = Logger::root(slog::Discard, o!()); - // let mut b: web3::types::Block = Default::default(); - - // // This is necessary because inside of BlockWithTriggers::new - // // there's a log for both fields. So just using Default above - // // gives None on them. - // b.number = Some(Default::default()); - // b.hash = Some(Default::default()); - let b = alloy_todo!(); + let b = Block::default(); - #[allow(unreachable_code)] let b = BlockWrapper::new(b); // Test that `BlockWithTriggers` sorts the triggers. @@ -180,23 +173,6 @@ fn test_trigger_dedup() { call4.transaction_index = 2; let call4 = EthereumTrigger::Call(Arc::new(call4)); - fn create_log(tx_index: u64, log_index: u64) -> Arc { - // Arc::new(Log { - // address: H160::default(), - // topics: vec![], - // data: Bytes::default(), - // block_hash: Some(H256::zero()), - // block_number: Some(U64::zero()), - // transaction_hash: Some(H256::zero()), - // transaction_index: Some(tx_index.into()), - // log_index: Some(log_index.into()), - // transaction_log_index: Some(log_index.into()), - // log_type: Some("".into()), - // removed: Some(false), - // }) - alloy_todo!() - } - let log1 = EthereumTrigger::Log(LogRef::FullLog(create_log(1, 0), None)); let log2 = EthereumTrigger::Log(LogRef::FullLog(create_log(1, 1), None)); let log3 = EthereumTrigger::Log(LogRef::FullLog(create_log(2, 5), None)); @@ -224,16 +200,8 @@ fn test_trigger_dedup() { let logger = Logger::root(slog::Discard, o!()); - // let mut b: web3::types::Block = Default::default(); - - // // This is necessary because inside of BlockWithTriggers::new - // // there's a log for both fields. So just using Default above - // // gives None on them. - // b.number = Some(Default::default()); - // b.hash = Some(Default::default()); - #[allow(unused_variables)] - let b = alloy_todo!(); + let b = Block::default(); #[allow(unreachable_code)] let b = BlockWrapper::new(b); diff --git a/chain/ethereum/src/trigger.rs b/chain/ethereum/src/trigger.rs index f08fe55220c..7cc21d45d9b 100644 --- a/chain/ethereum/src/trigger.rs +++ b/chain/ethereum/src/trigger.rs @@ -1,5 +1,4 @@ use graph::abi; -use graph::alloy_todo; use graph::blockchain::MappingTriggerTrait; use graph::blockchain::TriggerData; use graph::data::subgraph::API_VERSION_0_0_2; @@ -423,8 +422,7 @@ impl<'a> EthereumBlockData<'a> { } pub fn uncles_hash(&self) -> &B256 { - // &self.block.inner().header.uncles_hash - alloy_todo!() + &self.block.inner().header.ommers_hash } pub fn author(&self) -> &Address { @@ -576,9 +574,9 @@ impl<'a> EthereumEventData<'a> { self.log.log_index.unwrap_or(0) } - pub fn log_type(&self) -> &Option { - // &self.log.log_type - alloy_todo!() + pub fn log_type(&self) -> Option { + // This field was present in old rust-web3 Block, but alloy doesn't have it. + None } } diff --git a/graph/src/abi/event_ext.rs b/graph/src/abi/event_ext.rs index a9a1cd32f71..0145dadb6d5 100644 --- a/graph/src/abi/event_ext.rs +++ b/graph/src/abi/event_ext.rs @@ -48,28 +48,24 @@ impl EventExt for Event { #[cfg(test)] mod tests { use alloy::dyn_abi::DynSolValue; - use alloy::primitives::U256; - - use crate::alloy_todo; + use alloy::primitives::{LogData, U256}; use super::*; - fn make_log(_topics: &[[u8; 32]], _data: Vec) -> Log { - // Log { - // address: [1; 20].into(), - // topics: topics.iter().map(Into::into).collect(), - // data: data.into(), - // block_hash: None, - // block_number: None, - // transaction_hash: None, - // transaction_index: None, - // log_index: None, - // transaction_log_index: None, - // log_type: None, - // removed: None, - // } - - alloy_todo!() + fn make_log(topics: &[[u8; 32]], data: Vec) -> Log { + Log { + inner: alloy::primitives::Log { + address: [1; 20].into(), + data: LogData::new_unchecked(topics.iter().map(Into::into).collect(), data.into()), + }, + block_hash: None, + block_number: None, + block_timestamp: None, + transaction_hash: None, + transaction_index: None, + log_index: None, + removed: false, + } } #[test] diff --git a/graph/src/blockchain/types.rs b/graph/src/blockchain/types.rs index 48301a77705..e684af64dbd 100644 --- a/graph/src/blockchain/types.rs +++ b/graph/src/blockchain/types.rs @@ -208,28 +208,16 @@ impl slog::Value for BlockPtr { impl From for BlockPtr { fn from(b: BlockWrapper) -> BlockPtr { - BlockPtr::from((b.hash_b256().unwrap(), b.number_u64() as i32)) + BlockPtr::from((b.hash(), b.number_u64() as i32)) } } impl From<&BlockWrapper> for BlockPtr { fn from(b: &BlockWrapper) -> BlockPtr { - BlockPtr::from((b.hash_b256().unwrap(), b.number_u64() as i32)) + BlockPtr::from((b.hash(), b.number_u64() as i32)) } } -// impl From> for BlockPtr { -// fn from(b: Web3Block) -> BlockPtr { -// BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) -// } -// } - -// impl<'a, T> From<&'a Web3Block> for BlockPtr { -// fn from(b: &'a Web3Block) -> BlockPtr { -// BlockPtr::from((b.hash.unwrap(), b.number.unwrap().as_u64())) -// } -// } - impl From<(Vec, i32)> for BlockPtr { fn from((bytes, number): (Vec, i32)) -> Self { BlockPtr { diff --git a/graph/src/components/ethereum/types.rs b/graph/src/components/ethereum/types.rs index c4e3c9b286c..156437c61f3 100644 --- a/graph/src/components/ethereum/types.rs +++ b/graph/src/components/ethereum/types.rs @@ -9,7 +9,6 @@ use serde::{Deserialize, Serialize}; use std::sync::Arc; use crate::{ - alloy_todo, blockchain::{BlockPtr, BlockTime}, prelude::{alloy::rpc::types::Block as AlloyBlock, BlockNumber}, }; @@ -23,11 +22,6 @@ impl BlockWrapper { Self(block) } - pub fn hash_b256(&self) -> Option { - alloy_todo!() - // self.0.hash - } - pub fn hash(&self) -> B256 { self.0.header.hash } @@ -36,11 +30,6 @@ impl BlockWrapper { self.0.header.number } - pub fn number_web3_u64(&self) -> Option { - alloy_todo!() - // Some(u64_to_web3_u64(self.0.header.number)) - } - pub fn timestamp_u64(&self) -> u64 { self.0.header.timestamp } @@ -68,19 +57,31 @@ pub trait LightEthereumBlockExt { impl LightEthereumBlockExt for AlloyBlock { fn number(&self) -> BlockNumber { - alloy_todo!() + self.header.number as BlockNumber } fn timestamp(&self) -> BlockTime { - alloy_todo!() + let time = self.header.timestamp; + let time = i64::try_from(time).unwrap(); + BlockTime::since_epoch(time, 0) } - fn transaction_for_log(&self, _log: &Log) -> Option { - alloy_todo!() + fn transaction_for_log(&self, log: &Log) -> Option { + log.transaction_hash.and_then(|hash| { + self.transactions + .txns() + .find(|tx| tx.inner.hash() == &hash) + .cloned() + }) } - fn transaction_for_call(&self, _call: &EthereumCall) -> Option { - alloy_todo!() + fn transaction_for_call(&self, call: &EthereumCall) -> Option { + call.transaction_hash.and_then(|hash| { + self.transactions + .txns() + .find(|tx| tx.inner.hash() == &hash) + .cloned() + }) } fn parent_ptr(&self) -> Option { @@ -94,11 +95,11 @@ impl LightEthereumBlockExt for AlloyBlock { } fn format(&self) -> String { - alloy_todo!() + format!("{} ({})", self.header.number, self.header.hash) } fn block_ptr(&self) -> BlockPtr { - alloy_todo!() + BlockPtr::new(self.header.hash.into(), self.header.number as i32) } } @@ -231,18 +232,6 @@ impl EthereumCall { } } -impl From for BlockPtr { - fn from(b: EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash_b256().unwrap(), b.block.number())) - } -} - -impl<'a> From<&'a EthereumBlock> for BlockPtr { - fn from(b: &'a EthereumBlock) -> BlockPtr { - BlockPtr::from((b.block.hash_b256().unwrap(), b.block.number())) - } -} - impl<'a> From<&'a EthereumCall> for BlockPtr { fn from(call: &'a EthereumCall) -> BlockPtr { BlockPtr::from((call.block_hash, call.block_number)) diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 6b071f3648f..acaaaede027 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -176,13 +176,9 @@ pub mod prelude { }; pub use crate::log::split::split_logger; pub use crate::util::cache_weight::CacheWeight; - pub use crate::util::conversions::{ - alloy_address_to_h160, alloy_address_to_web3_address, alloy_log_to_web3_log, - alloy_transaction_receipt_to_web3_transaction_receipt, h160_to_alloy_address, h256_to_b256, - web3_address_to_alloy_address, - }; pub use crate::util::futures::{retry, TimeoutError}; pub use crate::util::stats::MovingStats; + pub use crate::util::test_utils::*; macro_rules! static_graphql { ($m:ident, $m2:ident, {$($n:ident,)*}) => { diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index f4cfad0da4b..4cf4cb2bc87 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -89,7 +89,7 @@ pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { } } -pub fn alloy_log_ref_to_web3_log_ref(log: &AlloyLog) -> &Web3Log { +pub fn alloy_log_ref_to_web3_log_ref(_log: &AlloyLog) -> &Web3Log { unimplemented!() } @@ -125,52 +125,3 @@ pub fn web3_block_to_alloy_block(_block: Web3Block) -> AlloyBlo "Block conversion from web3 to alloy not yet implemented - will be done when needed" ) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_h256_to_b256_conversion() { - let h = H256::from([1u8; 32]); - let b = h256_to_b256(h); - assert_eq!(b.as_slice(), &[1u8; 32]); - } - - #[test] - fn test_b256_to_h256_conversion() { - let b = B256::from([2u8; 32]); - let h = b256_to_h256(b); - assert_eq!(h.as_bytes(), &[2u8; 32]); - } - - #[test] - fn test_round_trip_conversion() { - let original_h = H256::from([42u8; 32]); - let b = h256_to_b256(original_h); - let converted_h = b256_to_h256(b); - assert_eq!(original_h, converted_h); - } - - #[test] - fn test_h160_to_alloy_address_conversion() { - let h = H160::from([1u8; 20]); - let addr = h160_to_alloy_address(h); - assert_eq!(addr.as_slice(), &[1u8; 20]); - } - - #[test] - fn test_alloy_address_to_h160_conversion() { - let addr = AlloyAddress::from([2u8; 20]); - let h = alloy_address_to_h160(addr); - assert_eq!(h.as_bytes(), &[2u8; 20]); - } - - #[test] - fn test_address_round_trip_conversion() { - let original_h = H160::from([42u8; 20]); - let addr = h160_to_alloy_address(original_h); - let converted_h = alloy_address_to_h160(addr); - assert_eq!(original_h, converted_h); - } -} diff --git a/graph/src/util/mod.rs b/graph/src/util/mod.rs index ea72fbee1dd..969dafc534e 100644 --- a/graph/src/util/mod.rs +++ b/graph/src/util/mod.rs @@ -38,3 +38,6 @@ pub mod herd_cache; /// Type conversion utilities between web3 and alloy types pub mod conversions; + +/// Test utilities for creating mock blockchain data structures +pub mod test_utils; diff --git a/graph/src/util/test_utils.rs b/graph/src/util/test_utils.rs new file mode 100644 index 00000000000..38b618560c4 --- /dev/null +++ b/graph/src/util/test_utils.rs @@ -0,0 +1,57 @@ +use alloy::consensus::{TxEnvelope, TxLegacy}; +use alloy::primitives::Address; +use alloy::rpc::types::Transaction; + +use crate::prelude::alloy::consensus::Header as ConsensusHeader; +use crate::prelude::alloy::primitives::B256; +use crate::prelude::alloy::rpc::types::{Block, Header}; + +/// Creates a minimal Alloy Block for testing purposes. +pub fn create_minimal_block_for_test(block_number: u64, block_hash: B256) -> Block { + // Create consensus header with defaults, but set the specific number + let mut consensus_header = ConsensusHeader::default(); + consensus_header.number = block_number; + + // Create RPC header with the specific hash + let rpc_header = Header { + hash: block_hash, + inner: consensus_header, + total_difficulty: None, + size: None, + }; + + // Create an empty block with this header + Block::empty(rpc_header) +} + +/// Generic function that creates a mock legacy Transaction from ANY log +pub fn create_dummy_transaction( + block_number: u64, + block_hash: B256, + transaction_index: Option, + transaction_hash: B256, +) -> Transaction { + use alloy::{ + consensus::transaction::Recovered, + consensus::Signed, + primitives::{Signature, U256}, + }; + + let tx = TxLegacy::default(); + + // Create a dummy signature + let signature = Signature::new(U256::from(0x1111), U256::from(0x2222), false); + + let signed_tx = Signed::new_unchecked(tx, signature, transaction_hash); + let envelope = TxEnvelope::Legacy(signed_tx); + + let recovered = Recovered::new_unchecked(envelope, Address::ZERO); + + Transaction { + inner: recovered, + block_hash: Some(block_hash), + block_number: Some(block_number), + transaction_index: transaction_index, + effective_gas_price: None, + } +} diff --git a/store/test-store/src/block_store.rs b/store/test-store/src/block_store.rs index 57f8752ab22..a55acbb4212 100644 --- a/store/test-store/src/block_store.rs +++ b/store/test-store/src/block_store.rs @@ -1,9 +1,10 @@ use std::{convert::TryFrom, str::FromStr, sync::Arc}; -use graph::alloy_todo; use graph::blockchain::{BlockTime, ChainIdentifier}; use graph::components::ethereum::BlockWrapper; -use graph::prelude::alloy::primitives::{B256, U256}; +use graph::prelude::alloy::consensus::Header as ConsensusHeader; +use graph::prelude::alloy::primitives::{Bloom, B256, U256}; +use graph::prelude::alloy::rpc::types::{Block, Header}; use lazy_static::lazy_static; use graph::components::store::BlockStore; @@ -104,18 +105,25 @@ impl FakeBlock { pub fn as_ethereum_block(&self) -> EthereumBlock { let parent_hash = B256::from_str(self.parent_hash.as_str()).expect("invalid parent hash"); + let block_hash = B256::from_str(self.hash.as_str()).expect("invalid block hash"); + + let mut consensus_header = ConsensusHeader::default(); + consensus_header.number = self.number as u64; + consensus_header.parent_hash = parent_hash; + consensus_header.logs_bloom = Bloom::default(); // Empty bloom filter for test blocks + if let Some(ts) = self.timestamp { + consensus_header.timestamp = ts.to::(); + } - // let mut block = web3::types::Block::default(); - // block.number = Some(self.number.into()); - // block.parent_hash = parent_hash; - // block.hash = Some(H256(self.block_hash().as_slice().try_into().unwrap())); - // if let Some(ts) = self.timestamp { - // block.timestamp = ts; - // } + let rpc_header = Header { + hash: block_hash, + inner: consensus_header, + total_difficulty: None, + size: None, + }; - let block = alloy_todo!(); + let block = Block::empty(rpc_header); - #[allow(unreachable_code)] EthereumBlock { block: Arc::new(BlockWrapper::new(block)), transaction_receipts: Vec::new(), diff --git a/store/test-store/tests/postgres/chain_head.rs b/store/test-store/tests/postgres/chain_head.rs index 5eea7196de0..da301ccbda8 100644 --- a/store/test-store/tests/postgres/chain_head.rs +++ b/store/test-store/tests/postgres/chain_head.rs @@ -318,7 +318,7 @@ fn check_ancestor( } let act_block = json::from_value::(act.0)?; - let act_hash = format!("{:x}", act_block.block.hash_b256().unwrap()); + let act_hash = format!("{:x}", act_block.block.hash()); let exp_hash = &exp.hash; if &act_hash != exp_hash { diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index a2b1530b13b..c20f3ff6e03 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -6,7 +6,7 @@ use super::{ test_ptr, CommonChainConfig, MutexBlockStreamBuilder, NoopAdapterSelector, NoopRuntimeAdapterBuilder, StaticBlockRefetcher, StaticStreamBuilder, Stores, TestChain, }; -use graph::alloy_todo; +use graph::abi; use graph::blockchain::block_stream::BlockWithTriggers; use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation}; use graph::blockchain::client::ChainClient; @@ -15,7 +15,11 @@ use graph::cheap_clone::CheapClone; use graph::components::ethereum::BlockWrapper; use graph::data_source::subgraph; use graph::prelude::alloy::primitives::{Address, B256, U256}; -use graph::prelude::{tiny_keccak, DeploymentHash, Entity, ENV_VARS}; +use graph::prelude::alloy::rpc::types::BlockTransactions; +use graph::prelude::{ + create_dummy_transaction, create_minimal_block_for_test, tiny_keccak, DeploymentHash, Entity, + ENV_VARS, +}; use graph::schema::EntityType; use graph_chain_ethereum::network::EthereumNetworkAdapters; use graph_chain_ethereum::trigger::LogRef; @@ -78,14 +82,8 @@ pub async fn chain( pub fn genesis() -> BlockWithTriggers { #[allow(unused_variables)] let ptr = test_ptr(0); - // let block: web3::types::Block = web3::types::Block { - // hash: Some(H256::from_slice(ptr.hash.as_slice())), - // number: Some(U64::from(ptr.number)), - // ..Default::default() - // }; - #[allow(unused_variables)] - let block = alloy_todo!(); + let block = create_minimal_block_for_test(ptr.number as u64, ptr.hash.as_b256()); #[allow(unreachable_code)] BlockWithTriggers:: { @@ -121,30 +119,14 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers parent_ptr.number); - #[allow(unused_variables)] - // A 0x000.. transaction is used so `push_test_log` can use it - // let transactions = vec![Transaction { - // hash: H256::zero(), - // block_hash: Some(H256::from_slice(ptr.hash.as_slice())), - // block_number: Some(ptr.number.into()), - // transaction_index: Some(0.into()), - // from: Some(H160::zero()), - // to: Some(H160::zero()), - // ..Default::default() - // }]; - - // let web3_block = web3::types::Block { - // hash: Some(H256::from_slice(ptr.hash.as_slice())), - // number: Some(U64::from(ptr.number)), - // parent_hash: H256::from_slice(parent_ptr.hash.as_slice()), - // transactions: transactions.clone(), - // ..Default::default() - // }; - #[allow(unused_variables)] - let web3_block = alloy_todo!(); - #[allow(unreachable_code)] + let dummy_txn = + create_dummy_transaction(ptr.number as u64, ptr.hash.as_b256(), Some(0), B256::ZERO); + let transactions = BlockTransactions::Full(vec![dummy_txn]); + let alloy_block = create_minimal_block_for_test(ptr.number as u64, ptr.hash.as_b256()) + .with_transactions(transactions); + BlockWithTriggers:: { - block: BlockFinality::Final(Arc::new(BlockWrapper::new(web3_block))), + block: BlockFinality::Final(Arc::new(BlockWrapper::new(alloy_block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, @@ -153,26 +135,30 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers, payload: impl Into) { - // let log = Arc::new(Log { - // address: Address::ZERO, - // topics: vec![tiny_keccak::keccak256(b"TestEvent(string)").into()], - // data: abi::DynSolValue::String(payload.into()).abi_encode().into(), - // block_hash: Some(B256::from_slice(block.ptr().hash.as_slice())), - // block_number: Some(block.ptr().number.into()), - // transaction_hash: Some(B256::from(U256::from(0))), - // transaction_index: Some(0.into()), - // log_index: Some(0.into()), - // transaction_log_index: Some(0.into()), - // log_type: None, - // removed: None, - // }); - // block - // .trigger_data - // .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( - // log, None, - // )))) - - alloy_todo!() + use graph::prelude::alloy::{self, primitives::LogData, rpc::types::Log}; + + let log = Arc::new(Log { + inner: alloy::primitives::Log { + address: Address::ZERO, + data: LogData::new_unchecked( + vec![tiny_keccak::keccak256(b"TestEvent(string)").into()], + abi::DynSolValue::String(payload.into()).abi_encode().into(), + ), + }, + block_hash: Some(B256::from_slice(block.ptr().hash.as_slice())), + block_number: Some(block.ptr().number as u64), + transaction_hash: Some(B256::from(U256::from(0))), + transaction_index: Some(0), + log_index: Some(0), + block_timestamp: None, + removed: false, + }); + + block + .trigger_data + .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( + log, None, + )))) } pub fn push_test_subgraph_trigger( @@ -205,31 +191,35 @@ pub fn push_test_command( test_command: impl Into, data: impl Into, ) { - // let log = Arc::new(Log { - // address: Address::zero(), - // topics: vec![tiny_keccak::keccak256(b"TestEvent(string,string)").into()], - // data: abi::DynSolValue::Tuple(vec![ - // abi::DynSolValue::String(test_command.into()), - // abi::DynSolValue::String(data.into()), - // ]) - // .abi_encode_params() - // .into(), - // block_hash: Some(B256::from_slice(block.ptr().hash.as_slice())), - // block_number: Some(block.ptr().number.into()), - // transaction_hash: Some(B256::from(U256::from(0))), - // transaction_index: Some(0.into()), - // log_index: Some(0.into()), - // transaction_log_index: Some(0.into()), - // log_type: None, - // removed: None, - // }); - // block - // .trigger_data - // .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( - // log, None, - // )))) - - alloy_todo!() + use graph::prelude::alloy::{self, primitives::LogData, rpc::types::Log}; + + let log = Arc::new(Log { + inner: alloy::primitives::Log { + address: Address::ZERO, + data: LogData::new_unchecked( + vec![tiny_keccak::keccak256(b"TestEvent(string)").into()], + abi::DynSolValue::Tuple(vec![ + abi::DynSolValue::String(test_command.into()), + abi::DynSolValue::String(data.into()), + ]) + .abi_encode_params() + .into(), + ), + }, + block_hash: Some(block.ptr().hash.as_b256()), + block_number: Some(block.ptr().number as u64), + transaction_hash: Some(B256::from(U256::from(0))), + transaction_index: Some(0), + log_index: Some(0), + block_timestamp: None, + removed: false, + }); + + block + .trigger_data + .push(Trigger::Chain(EthereumTrigger::Log(LogRef::FullLog( + log, None, + )))) } pub fn push_test_polling_trigger(block: &mut BlockWithTriggers) { From 71b59f07dea9d52aca0c18e065ec0aaa8b261cc2 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 2 Jul 2025 17:27:30 +0530 Subject: [PATCH 43/44] Remove unneccessary conversion functions --- chain/ethereum/src/adapter.rs | 2 +- chain/ethereum/src/ethereum_adapter.rs | 53 ++++++------ chain/ethereum/src/tests.rs | 4 +- graph/src/util/conversions.rs | 115 +------------------------ node/src/manager/commands/chain.rs | 6 +- store/test-store/src/block_store.rs | 4 +- tests/src/fixture/ethereum.rs | 7 +- tests/tests/integration_tests.rs | 6 +- 8 files changed, 43 insertions(+), 154 deletions(-) diff --git a/chain/ethereum/src/adapter.rs b/chain/ethereum/src/adapter.rs index 160397dcade..7974381aa6b 100644 --- a/chain/ethereum/src/adapter.rs +++ b/chain/ethereum/src/adapter.rs @@ -1159,7 +1159,7 @@ pub trait EthereumAdapter: Send + Sync + 'static { logger: Logger, chain_store: Arc, block_hashes: HashSet, - ) -> Result>, Error>; + ) -> Result>, Error>; /// Find a block by its hash. async fn block_by_hash( diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 9a654196615..54ad2ceb9ba 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -20,7 +20,6 @@ use graph::futures03::future::try_join_all; use graph::futures03::{ self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt, }; -use graph::prelude::alloy::consensus::BlockHeader; use graph::prelude::alloy::primitives::Address; use graph::prelude::alloy::rpc::types::Transaction; use graph::prelude::{ @@ -45,8 +44,6 @@ use graph::prelude::{ use graph::slog::o; use graph::tokio::sync::RwLock; use graph::tokio::time::timeout; -use graph::util::conversions::alloy_block_to_block; -use graph::util::conversions::alloy_block_to_block_arc; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, IngestorError}, prelude::{ @@ -718,7 +715,7 @@ impl EthereumAdapter { &self, logger: Logger, ids: Vec, - ) -> impl futures03::Stream, Error>> + Send { + ) -> impl futures03::Stream, Error>> + Send { let alloy = self.alloy.clone(); futures03::stream::iter(ids.into_iter().map(move |hash| { @@ -739,12 +736,14 @@ impl EthereumAdapter { .await .map_err(Error::from) .and_then(|block| { - block.map(Arc::new).ok_or_else(|| { - anyhow::anyhow!( - "Ethereum node did not find block {:?}", - hash - ) - }) + block + .map(|b| Arc::new(LightEthereumBlock::new(b))) + .ok_or_else(|| { + anyhow::anyhow!( + "Ethereum node did not find block {:?}", + hash + ) + }) }) } }) @@ -1340,7 +1339,7 @@ impl EthereumAdapterTrait for EthereumAdapter { if block.transactions.is_empty() { trace!(logger, "Block {} contains no transactions", block_hash); return Ok(EthereumBlock { - block: Arc::new(alloy_block_to_block(block)), + block: Arc::new(LightEthereumBlock::new(block)), transaction_receipts: Vec::new(), }); } @@ -1359,7 +1358,7 @@ impl EthereumAdapterTrait for EthereumAdapter { fetch_receipts_with_retry(alloy, hashes, block_hash, logger, supports_block_receipts) .await .map(|transaction_receipts| EthereumBlock { - block: Arc::new(alloy_block_to_block(block)), + block: Arc::new(LightEthereumBlock::new(block)), transaction_receipts: transaction_receipts .into_iter() .map(|receipt| receipt) @@ -1611,10 +1610,10 @@ impl EthereumAdapterTrait for EthereumAdapter { logger: Logger, chain_store: Arc, block_hashes: HashSet, - ) -> Result>, Error> { + ) -> Result>, Error> { let block_hashes: Vec<_> = block_hashes.iter().cloned().collect(); // Search for the block in the store first then use json-rpc as a backup. - let mut blocks: Vec> = chain_store + let mut blocks: Vec<_> = chain_store .cheap_clone() .blocks(block_hashes.iter().map(|&b| b.into()).collect::>()) .await @@ -1622,24 +1621,24 @@ impl EthereumAdapterTrait for EthereumAdapter { .unwrap_or_default() .into_iter() .filter_map(|value| json::from_value(value).ok()) - .map(Arc::new) + .map(|b| Arc::new(LightEthereumBlock::new(b))) .collect(); let missing_blocks = Vec::from_iter( block_hashes .into_iter() - .filter(|hash| !blocks.iter().any(|b| b.header.hash == *hash)), + .filter(|hash| !blocks.iter().any(|b| b.hash() == *hash)), ); // Return a stream that lazily loads batches of blocks. debug!(logger, "Requesting {} block(s)", missing_blocks.len()); - let new_blocks: Vec> = self + let new_blocks: Vec<_> = self .load_blocks_rpc(logger.clone(), missing_blocks) .try_collect() .await?; let upsert_blocks: Vec<_> = new_blocks .iter() - .map(|block| BlockFinality::Final(alloy_block_to_block_arc(block.clone()))) + .map(|block| BlockFinality::Final(block.clone())) .collect(); let block_refs: Vec<_> = upsert_blocks .iter() @@ -1649,7 +1648,7 @@ impl EthereumAdapterTrait for EthereumAdapter { error!(logger, "Error writing to block cache {}", e); } blocks.extend(new_blocks); - blocks.sort_by_key(|block| block.header.number); + blocks.sort_by_key(|block| block.number()); Ok(blocks) } } @@ -1792,15 +1791,15 @@ pub(crate) async fn blocks_with_triggers( .await? .into_iter() .map( - move |block| match triggers_by_block.remove(&(block.header.number() as BlockNumber)) { + move |block| match triggers_by_block.remove(&(block.number())) { Some(triggers) => Ok(BlockWithTriggers::new( - BlockFinality::Final(alloy_block_to_block_arc(block)), + BlockFinality::Final(block), triggers, &logger2, )), None => Err(anyhow!( "block {} not found in `triggers_by_block`", - BlockPtr::new(block.header.hash.into(), block.header.number as i32) + block.block_ptr() )), }, ) @@ -2612,12 +2611,11 @@ mod tests { EthereumBlockWithCalls, }; use graph::blockchain::BlockPtr; - use graph::components::ethereum::BlockWrapper; use graph::prelude::alloy::primitives::{Address, Bytes, B256}; use graph::prelude::alloy::providers::mock::Asserter; use graph::prelude::alloy::providers::ProviderBuilder; use graph::prelude::tokio::{self}; - use graph::prelude::{create_minimal_block_for_test, EthereumCall}; + use graph::prelude::{create_minimal_block_for_test, EthereumCall, LightEthereumBlock}; use jsonrpc_core::serde_json::{self, Value}; use std::collections::HashSet; use std::iter::FromIterator; @@ -2627,10 +2625,9 @@ mod tests { fn parse_block_triggers_every_block() { let block = create_minimal_block_for_test(2, hash(2)); - #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(block)), + block: Arc::new(LightEthereumBlock::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2772,7 +2769,7 @@ mod tests { #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(block)), + block: Arc::new(LightEthereumBlock::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { @@ -2803,7 +2800,7 @@ mod tests { #[allow(unreachable_code)] let block = EthereumBlockWithCalls { ethereum_block: EthereumBlock { - block: Arc::new(BlockWrapper::new(block)), + block: Arc::new(LightEthereumBlock::new(block)), ..Default::default() }, calls: Some(vec![EthereumCall { diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index 94cf007d531..11c3f29e33f 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -124,7 +124,7 @@ fn test_trigger_ordering() { let b = Block::default(); - let b = BlockWrapper::new(b); + let b = LightEthereumBlock::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( @@ -204,7 +204,7 @@ fn test_trigger_dedup() { let b = Block::default(); #[allow(unreachable_code)] - let b = BlockWrapper::new(b); + let b = LightEthereumBlock::new(b); // Test that `BlockWithTriggers` sorts the triggers. let block_with_triggers = BlockWithTriggers::::new( diff --git a/graph/src/util/conversions.rs b/graph/src/util/conversions.rs index 4cf4cb2bc87..355e66d561c 100644 --- a/graph/src/util/conversions.rs +++ b/graph/src/util/conversions.rs @@ -1,127 +1,14 @@ -use std::sync::Arc; - -use web3::types::Bytes; - -use crate::components::ethereum::BlockWrapper; -use crate::prelude::alloy::primitives::{Address as AlloyAddress, B256}; -use crate::prelude::alloy::rpc::types::{ - Block as AlloyBlock, Log as AlloyLog, TransactionReceipt as AlloyTransactionReceipt, -}; /// Type conversion utilities between web3 and alloy types -use crate::prelude::web3::types::{ - Address as Web3Address, Block as Web3Block, Log as Web3Log, Transaction as Web3Transaction, - TransactionReceipt as Web3TransactionReceipt, H160, H256, U256, U64, -}; - -/// Converts H256 to alloy B256 -pub fn h256_to_b256(h: H256) -> B256 { - B256::from_slice(h.as_bytes()) -} - -/// Converts alloy B256 to H256 -pub fn b256_to_h256(b: B256) -> H256 { - H256::from_slice(b.as_slice()) -} - -pub fn web3_u64_from_option(opt: Option) -> U64 { - U64::from(opt.unwrap_or(0)) -} - -pub fn u64_to_web3_u256(u: u64) -> U256 { - U256::from(u) -} - -pub fn bool_to_web3_u64(b: bool) -> U64 { - U64::from(if b { 1 } else { 0 }) -} - -pub fn u64_to_web3_u64(u: u64) -> U64 { - U64::from(u) -} -/// Converts web3 H160 to alloy Address -pub fn h160_to_alloy_address(h: H160) -> AlloyAddress { - AlloyAddress::from_slice(h.as_bytes()) -} - -/// Converts alloy Address to web3 H160 -pub fn alloy_address_to_h160(addr: AlloyAddress) -> H160 { - H160::from_slice(addr.as_slice()) -} - -/// Converts web3 Address to alloy Address -pub fn web3_address_to_alloy_address(addr: Web3Address) -> AlloyAddress { - h160_to_alloy_address(addr) -} - -/// Converts alloy Address to web3 Address -pub fn alloy_address_to_web3_address(addr: AlloyAddress) -> Web3Address { - alloy_address_to_h160(addr) -} +use crate::prelude::web3::types::U256; // u256 to web3 U256 pub fn alloy_u256_to_web3_u256(_u: alloy::primitives::U256) -> U256 { unimplemented!(); } -pub fn alloy_bytes_to_web3_bytes(_b: alloy::primitives::Bytes) -> Bytes { - unimplemented!(); -} - -// u256 to alloy U256 -pub fn web3_u256_to_alloy_u256(u: U256) -> U256 { - U256::from(u) -} - -/// Converts alloy Log to web3 Log -pub fn alloy_log_to_web3_log(log: AlloyLog) -> Web3Log { - Web3Log { - address: alloy_address_to_h160(log.address()), - topics: log.topics().iter().map(|t| b256_to_h256(*t)).collect(), - data: log.data().data.clone().into(), - block_hash: log.block_hash.map(b256_to_h256), - block_number: log.block_number.map(|n| U64::from(n)), - transaction_hash: log.transaction_hash.map(b256_to_h256), - transaction_index: log.transaction_index.map(|i| U64::from(i)), - log_index: log.log_index.map(|i| U256::from(i)), - transaction_log_index: None, // alloy Log doesn't have transaction_log_index - log_type: None, // alloy Log doesn't have log_type - removed: Some(log.removed), - } -} - -pub fn alloy_log_ref_to_web3_log_ref(_log: &AlloyLog) -> &Web3Log { - unimplemented!() -} - #[macro_export] macro_rules! alloy_todo { () => { todo!() }; } - -pub fn alloy_transaction_receipt_to_web3_transaction_receipt( - _receipt: Arc, -) -> Arc { - unimplemented!("TransactionReceipt conversion not yet implemented - will be done when needed") -} - -/// Converts alloy Block to web3 Block -pub fn alloy_block_to_block_arc(_block: Arc) -> Arc { - unimplemented!( - "Block conversion from alloy to web3 not yet implemented - will be done when needed" - ) -} - -pub fn alloy_block_to_block(_block: AlloyBlock) -> BlockWrapper { - unimplemented!( - "Block conversion from alloy to web3 not yet implemented - will be done when needed" - ) -} - -/// Converts web3 Block to alloy Block -pub fn web3_block_to_alloy_block(_block: Web3Block) -> AlloyBlock { - unimplemented!( - "Block conversion from web3 to alloy not yet implemented - will be done when needed" - ) -} diff --git a/node/src/manager/commands/chain.rs b/node/src/manager/commands/chain.rs index 993c265da3c..caa102d8538 100644 --- a/node/src/manager/commands/chain.rs +++ b/node/src/manager/commands/chain.rs @@ -12,9 +12,9 @@ use graph::components::store::ChainIdStore; use graph::components::store::StoreError; use graph::prelude::BlockNumber; use graph::prelude::ChainStore as _; +use graph::prelude::LightEthereumBlock; use graph::prelude::{anyhow, anyhow::bail}; use graph::slog::Logger; -use graph::util::conversions::alloy_block_to_block; use graph::{ components::store::BlockStore as _, components::store::ChainHeadStore as _, prelude::anyhow::Error, @@ -279,7 +279,9 @@ pub async fn ingest( let hash = block.header.hash; let number = block.header.number; // For inserting the block, it doesn't matter whether the block is final or not. - let block = Arc::new(BlockFinality::Final(Arc::new(alloy_block_to_block(block)))); + let block = Arc::new(BlockFinality::Final(Arc::new(LightEthereumBlock::new( + block, + )))); chain_store.upsert_block(block).await?; let hash = hash.into(); diff --git a/store/test-store/src/block_store.rs b/store/test-store/src/block_store.rs index a55acbb4212..c4fcb983197 100644 --- a/store/test-store/src/block_store.rs +++ b/store/test-store/src/block_store.rs @@ -1,10 +1,10 @@ use std::{convert::TryFrom, str::FromStr, sync::Arc}; use graph::blockchain::{BlockTime, ChainIdentifier}; -use graph::components::ethereum::BlockWrapper; use graph::prelude::alloy::consensus::Header as ConsensusHeader; use graph::prelude::alloy::primitives::{Bloom, B256, U256}; use graph::prelude::alloy::rpc::types::{Block, Header}; +use graph::prelude::LightEthereumBlock; use lazy_static::lazy_static; use graph::components::store::BlockStore; @@ -125,7 +125,7 @@ impl FakeBlock { let block = Block::empty(rpc_header); EthereumBlock { - block: Arc::new(BlockWrapper::new(block)), + block: Arc::new(LightEthereumBlock::new(block)), transaction_receipts: Vec::new(), } } diff --git a/tests/src/fixture/ethereum.rs b/tests/src/fixture/ethereum.rs index c20f3ff6e03..bf43c565f18 100644 --- a/tests/src/fixture/ethereum.rs +++ b/tests/src/fixture/ethereum.rs @@ -12,13 +12,12 @@ use graph::blockchain::block_stream::{EntityOperationKind, EntitySourceOperation use graph::blockchain::client::ChainClient; use graph::blockchain::{BlockPtr, Trigger, TriggersAdapterSelector}; use graph::cheap_clone::CheapClone; -use graph::components::ethereum::BlockWrapper; use graph::data_source::subgraph; use graph::prelude::alloy::primitives::{Address, B256, U256}; use graph::prelude::alloy::rpc::types::BlockTransactions; use graph::prelude::{ create_dummy_transaction, create_minimal_block_for_test, tiny_keccak, DeploymentHash, Entity, - ENV_VARS, + LightEthereumBlock, ENV_VARS, }; use graph::schema::EntityType; use graph_chain_ethereum::network::EthereumNetworkAdapters; @@ -87,7 +86,7 @@ pub fn genesis() -> BlockWithTriggers { #[allow(unreachable_code)] BlockWithTriggers:: { - block: BlockFinality::Final(Arc::new(BlockWrapper::new(block))), + block: BlockFinality::Final(Arc::new(LightEthereumBlock::new(block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, @@ -126,7 +125,7 @@ pub fn empty_block(parent_ptr: BlockPtr, ptr: BlockPtr) -> BlockWithTriggers { - block: BlockFinality::Final(Arc::new(BlockWrapper::new(alloy_block))), + block: BlockFinality::Final(Arc::new(LightEthereumBlock::new(alloy_block))), trigger_data: vec![Trigger::Chain(EthereumTrigger::Block( ptr, EthereumBlockTriggerType::End, diff --git a/tests/tests/integration_tests.rs b/tests/tests/integration_tests.rs index 16aa7041ea4..e4097d21917 100644 --- a/tests/tests/integration_tests.rs +++ b/tests/tests/integration_tests.rs @@ -17,7 +17,7 @@ use anyhow::{anyhow, bail, Context, Result}; use graph::futures03::StreamExt; use graph::prelude::alloy::primitives::U256; use graph::prelude::serde_json::{json, Value}; -use graph::util::conversions::alloy_u256_to_web3_u256; +use graph::prelude::web3; use graph_tests::contract::Contract; use graph_tests::helpers::{run_checked, TestFile}; use graph_tests::subgraph::Subgraph; @@ -569,6 +569,10 @@ async fn subgraph_data_sources(ctx: TestContext) -> anyhow::Result<()> { Ok(()) } +fn alloy_u256_to_web3_u256(u: U256) -> web3::types::U256 { + web3::types::U256::from_little_endian(u.as_le_slice()) +} + async fn test_topic_filters(ctx: TestContext) -> anyhow::Result<()> { let subgraph = ctx.subgraph; assert!(subgraph.healthy); From 56eee8bb1da55b35a70b74656b784062dded3266 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 2 Jul 2025 17:34:07 +0530 Subject: [PATCH 44/44] update failing tests --- chain/ethereum/src/tests.rs | 3 +-- graph/src/abi/event_ext.rs | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/chain/ethereum/src/tests.rs b/chain/ethereum/src/tests.rs index 11c3f29e33f..e6abb213af9 100644 --- a/chain/ethereum/src/tests.rs +++ b/chain/ethereum/src/tests.rs @@ -2,7 +2,6 @@ use std::sync::Arc; use graph::{ blockchain::{block_stream::BlockWithTriggers, BlockPtr, Trigger}, - components::ethereum::BlockWrapper, prelude::{ alloy::{ self, @@ -10,7 +9,7 @@ use graph::{ rpc::types::{Block, Log}, }, rand::{self, Rng}, - EthereumCall, + EthereumCall, LightEthereumBlock, }, slog::{self, o, Logger}, }; diff --git a/graph/src/abi/event_ext.rs b/graph/src/abi/event_ext.rs index 0145dadb6d5..94088dfcaae 100644 --- a/graph/src/abi/event_ext.rs +++ b/graph/src/abi/event_ext.rs @@ -130,7 +130,10 @@ mod tests { let log = make_log(&[topic_0, a, a, a, a], b); let err = event.decode_log(&log).unwrap_err(); - assert_eq!(err.to_string(), "log has an invalid number of topics"); + assert_eq!( + err.to_string(), + "invalid log topic list length: expected 2 topics, got 5" + ); } #[test]