diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c433336..d1000d74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: uses: Leafwing-Studios/cargo-cache@43ec9a5bad6e7f174e7fc65dcf533de75ff65881 # v2 - name: prepare build env - run: sudo apt-get install -y lld librdkafka-dev libsasl2-dev + run: sudo apt-get install -y lld librdkafka-dev libsasl2-dev protobuf-compiler - run: cargo check - run: cargo clippy -- -Dwarnings --force-warn deprecated --force-warn dead-code diff --git a/Cargo.lock b/Cargo.lock index 4f49c5c8..b9002679 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d1aecf3cab3d0e7383064ce488616434b4ade10d8904dff422e74203c712f" +checksum = "48dff4dd98e17de00203f851800bbc8b76eb29a4d4e3e44074614338b7a3308d" dependencies = [ "alloy-consensus", "alloy-contract", @@ -59,9 +59,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5674914c2cfdb866c21cb0c09d82374ee39a1395cf512e7515f4c014083b3fff" +checksum = "4195a29a4b87137b2bb02105e746102873bc03561805cf45c0e510c961f160e6" dependencies = [ "alloy-primitives", "num_enum", @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c6ad411efe0f49e0e99b9c7d8749a1eb55f6dbf74a1bc6953ab285b02c4f67" +checksum = "eda689f7287f15bd3582daba6be8d1545bad3740fd1fb778f629a1fe866bb43b" dependencies = [ "alloy-eips", "alloy-primitives", @@ -90,14 +90,14 @@ dependencies = [ "secp256k1", "serde", "serde_with", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-consensus-any" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf397edad57b696501702d5887e4e14d7d0bbae9fbb6439e148d361f7254f45" +checksum = "2b5659581e41e8fe350ecc3593cb5c9dcffddfd550896390f2b78a07af67b0fa" dependencies = [ "alloy-consensus", "alloy-eips", @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977b97d271159578afcb26e39e1ca5ce1a7f937697793d7d571b0166dd8b8225" +checksum = "944085cf3ac8f32d96299aa26c03db7c8ca6cdaafdbc467910b889f0328e6b70" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -126,14 +126,14 @@ dependencies = [ "futures", "futures-util", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-core" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad31216895d27d307369daa1393f5850b50bbbd372478a9fa951c095c210627e" +checksum = "d47400608fc869727ad81dba058d55f97b29ad8b5c5256d9598523df8f356ab6" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b95b3deca680efc7e9cba781f1a1db352fa1ea50e6384a514944dcf4419e652" +checksum = "d9e8a436f0aad7df8bb47f144095fba61202265d9f5f09a70b0e3227881a668e" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -169,7 +169,7 @@ dependencies = [ "alloy-rlp", "crc", "serde", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] @@ -192,14 +192,14 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "serde", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-eips" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749b8449e4daf7359bdf1dabdba6ce424ff8b1bdc23bdb795661b2e991a08d87" +checksum = "6f35887da30b5fc50267109a3c61cd63e6ca1f45967983641053a40ee83468c1" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fcbae2107f3f2df2b02bb7d9e81e8aa730ae371ca9dd7fd0c81c3d0cb78a452" +checksum = "11d4009efea6f403b3a80531f9c6f70fc242399498ff71196a1688cc1c901f44" dependencies = [ "alloy-eips", "alloy-primitives", @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15516116086325c157c18261d768a20677f0f699348000ed391d4ad0dcb82530" +checksum = "459f98c6843f208856f338bfb25e65325467f7aff35dfeb0484d0a76e059134b" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -243,24 +243,24 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc30b0e20fcd0843834ecad2a716661c7b9d5aca2486f8e96b93d5246eb83e06" +checksum = "883dee3b4020fcb5667ee627b4f401e899dad82bf37b246620339dd980720ed9" dependencies = [ "alloy-primitives", "alloy-sol-types", "http 1.3.1", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] [[package]] name = "alloy-network" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaeb681024cf71f5ca14f3d812c0a8d8b49f13f7124713538e66d74d3bfe6aff" +checksum = "cd6e5b8ac1654a05c224390008e43634a2bdc74e181e02cf8ed591d8b3d4ad08" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -279,14 +279,14 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-network-primitives" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a03ad273e1c55cc481889b4130e82860e33624e6969e9a08854e0f3ebe659295" +checksum = "80d7980333dd9391719756ac28bc2afa9baa705fc70ffd11dc86ab078dd64477" dependencies = [ "alloy-consensus", "alloy-eips", @@ -297,9 +297,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6177ed26655d4e84e00b65cb494d4e0b8830e7cae7ef5d63087d445a2600fb55" +checksum = "3cfebde8c581a5d37b678d0a48a32decb51efd7a63a08ce2517ddec26db705c8" dependencies = [ "alloy-rlp", "bytes", @@ -307,14 +307,14 @@ dependencies = [ "const-hex", "derive_more", "foldhash", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "indexmap 2.10.0", "itoa", "k256", "keccak-asm", "paste", "proptest", - "rand 0.9.1", + "rand 0.9.2", "ruint", "rustc-hash", "serde", @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc164acf8c41c756e76c7aea3be8f0fb03f8a3ef90a33e3ddcea5d1614d8779" +checksum = "478a42fe167057b7b919cd8b0c2844f0247f667473340dad100eaf969de5754e" dependencies = [ "alloy-chains", "alloy-consensus", @@ -348,14 +348,13 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "http 1.3.1", "lru", "parking_lot", "pin-project 1.1.10", "reqwest", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tracing", "url", @@ -381,20 +380,19 @@ checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "alloy-rpc-client" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c44d31bcb9afad460915fe1fba004a2af5a07a3376c307b9bdfeec3678c209" +checksum = "8a0c6d723fbdf4a87454e2e3a275e161be27edcfbf46e2e3255dd66c138634b6" dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", "alloy-transport-http", - "async-stream", "futures", "pin-project 1.1.10", "reqwest", @@ -404,16 +402,15 @@ dependencies = [ "tokio-stream", "tower", "tracing", - "tracing-futures", "url", "wasmtimer", ] [[package]] name = "alloy-rpc-types" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba2cf3d3c6ece87f1c6bb88324a997f28cf0ad7e98d5e0b6fa91c4003c30916" +checksum = "c41492dac39365b86a954de86c47ec23dcc7452cdb2fde591caadc194b3e34c6" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -423,9 +420,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5b22062142ce3b2ed3374337d4b343437e5de6959397f55d2c9fe2c2ce0162" +checksum = "8f7eb22670a972ad6c222a6c6dac3eef905579acffe9d63ab42be24c7d158535" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -434,9 +431,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391e59f81bacbffc7bddd2da3a26d6eec0e2058e9237c279e9b1052bdf21b49e" +checksum = "b777b98526bbe5b7892ca22a7fd5f18ed624ff664a79f40d0f9f2bf94ba79a84" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -449,14 +446,15 @@ dependencies = [ "itertools 0.14.0", "serde", "serde_json", - "thiserror 2.0.12", + "serde_with", + "thiserror 2.0.15", ] [[package]] name = "alloy-serde" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea08bc854235d4dff08fd57df8033285c11b8d7548b20c6da218194e7e6035f" +checksum = "ee8d2c52adebf3e6494976c8542fbdf12f10123b26e11ad56f77274c16a2a039" dependencies = [ "alloy-primitives", "serde", @@ -465,9 +463,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb3759f85ef5f010a874d9ebd5ee6ce01cac65211510863124e0ebac6552db0" +checksum = "7c0494d1e0f802716480aabbe25549c7f6bc2a25ff33b08fd332bbb4b7d06894" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -477,14 +475,14 @@ dependencies = [ "either", "elliptic-curve", "k256", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-signer-aws" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7942b850ec7be43de89b2680321d7921b7620b25be53b9981aae6fb29daa9e97" +checksum = "0559495d87c099f7dbd0804145032e6a16ee675d1d2a15e98dc2658d64265cde" dependencies = [ "alloy-consensus", "alloy-network", @@ -494,15 +492,15 @@ dependencies = [ "aws-sdk-kms", "k256", "spki", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] [[package]] name = "alloy-signer-gcp" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74809e45053bd43d24338e618202ebea68d5660aa9632d77b0244faa2dcaa9d1" +checksum = "946fbac85c43e1f73db388629e2115c41c4211ec8532bc46514d8153e81e818b" dependencies = [ "alloy-consensus", "alloy-network", @@ -512,15 +510,15 @@ dependencies = [ "gcloud-sdk", "k256", "spki", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] [[package]] name = "alloy-signer-ledger" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c7e67367bc2b1d5790236448d2402865a4f0bc2b53cfda06d71b7ba3dbdffd" +checksum = "d4891d26fe418793186c30ea49451da8b5be2d9368547c9f1877002d3b0a192a" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -532,15 +530,15 @@ dependencies = [ "coins-ledger", "futures-util", "semver 1.0.26", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] [[package]] name = "alloy-signer-local" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d95902d29e1290809e1c967a1e974145b44b78f6e3e12fc07a60c1225e3df0" +checksum = "59c2435eb8979a020763ced3fb478932071c56e5f75ea86db41f320915d325ba" dependencies = [ "alloy-consensus", "alloy-network", @@ -549,28 +547,28 @@ dependencies = [ "async-trait", "k256", "rand 0.8.5", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "alloy-sol-macro" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a14f21d053aea4c6630687c2f4ad614bed4c81e14737a9b904798b24f30ea849" +checksum = "aedac07a10d4c2027817a43cc1f038313fc53c7ac866f7363239971fd01f9f18" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d99282e7c9ef14eb62727981a985a01869e586d1dec729d3bb33679094c100" +checksum = "24f9a598f010f048d8b8226492b6401104f5a5c1273c2869b72af29b48bb4ba9" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -580,16 +578,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda029f955b78e493360ee1d7bd11e1ab9f2a220a5715449babc79d6d0a01105" +checksum = "f494adf9d60e49aa6ce26dfd42c7417aa6d4343cf2ae621f20e4d92a5ad07d85" dependencies = [ "alloy-json-abi", "const-hex", @@ -599,15 +597,15 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.104", + "syn 2.0.106", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10db1bd7baa35bc8d4a1b07efbf734e73e5ba09f2580fb8cee3483a36087ceb2" +checksum = "52db32fbd35a9c0c0e538b58b81ebbae08a51be029e7ad60e08b60481c2ec6c3" dependencies = [ "serde", "winnow", @@ -615,9 +613,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58377025a47d8b8426b3e4846a251f2c1991033b27f517aade368146f6ab1dfe" +checksum = "a285b46e3e0c177887028278f04cc8262b76fd3b8e0e20e93cea0a58c35f5ac5" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -627,12 +625,13 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcdf4b7fc58ebb2605b2fc5a33dae5cf15527ea70476978351cc0db1c596ea93" +checksum = "3c0107675e10c7f248bf7273c1e7fdb02409a717269cc744012e6f3c39959bfb" dependencies = [ "alloy-json-rpc", "alloy-primitives", + "auto_impl", "base64", "derive_more", "futures", @@ -640,7 +639,7 @@ dependencies = [ "parking_lot", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tower", "tracing", @@ -650,9 +649,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4b0f3a9c28bcd3761504d9eb3578838d6d115c8959fc1ea05f59a3a8f691af" +checksum = "78e3736701b5433afd06eecff08f0688a71a10e0e1352e0bbf0bed72f0dd4e35" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -681,15 +680,15 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.17" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79bf2869e66904b2148c809e7a75e23ca26f5d7b46663a149a1444fb98a69d1d" +checksum = "6acb36318dfa50817154064fea7932adf2eec3f51c86680e2b37d7e8906c66bb" dependencies = [ "alloy-primitives", "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -707,11 +706,61 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "anymap3" @@ -860,9 +909,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40f6024f3f856663b45fd0c9b6f2024034a702f453549449e0d84a305900dad4" +checksum = "ddb939d66e4ae03cee6091612804ba446b12878410cfa17f785f4dd67d4014e8" dependencies = [ "flate2", "futures-core", @@ -890,18 +939,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -918,7 +967,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -929,9 +978,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-credential-types" -version = "1.2.3" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687bc16bc431a8533fe0097c7f0182874767f920989d7260950172ae8e3c4465" +checksum = "1541072f81945fa1251f8795ef6c92c4282d74d59f88498ae7d4bf00f0ebdad9" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -941,9 +990,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.5.8" +version = "1.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6c68419d8ba16d9a7463671593c54f81ba58cab466e9b759418da606dcc2e2" +checksum = "c034a1bc1d70e16e7f4e4caf7e9f7693e4c9c24cd91cf17c2a0b21abaebc7c8b" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -965,9 +1014,9 @@ dependencies = [ [[package]] name = "aws-sdk-kms" -version = "1.77.0" +version = "1.84.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cd57d0c1a5bd6c7eaa2b26462e046d5ca7b72189346718d2435dfc48bfa988b" +checksum = "98037a2a0745914d2f0fee41acb6cf88a76f0ed31dd75753b4dc318aa5a4da39" dependencies = [ "aws-credential-types", "aws-runtime", @@ -987,9 +1036,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfb9021f581b71870a17eac25b52335b82211cdc092e02b6876b2bcefa61666" +checksum = "084c34162187d39e3740cb635acd73c4e3a551a36146ad6fe8883c929c9f876c" dependencies = [ "aws-credential-types", "aws-smithy-http", @@ -1020,9 +1069,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.62.1" +version = "0.62.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99335bec6cdc50a346fda1437f9fefe33abf8c99060739a546a16457f2862ca9" +checksum = "7c4dacf2d38996cf729f55e7a762b30918229917eca115de45dfa8dfb97796c9" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", @@ -1058,9 +1107,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.8.3" +version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14302f06d1d5b7d333fd819943075b13d27c7700b414f574c3c35859bfb55d5e" +checksum = "9e107ce0783019dbff59b3a244aa0c114e4a8c9d93498af9162608cd5474e796" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -1081,9 +1130,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.8.1" +version = "1.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8531b6d8882fd8f48f82a9754e682e29dd44cff27154af51fa3eb730f59efb" +checksum = "75d52251ed4b9776a3e8487b2a01ac915f73b2da3af8fc1e77e0fce697a550d4" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -1121,9 +1170,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.3.7" +version = "1.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a322fec39e4df22777ed3ad8ea868ac2f94cd15e1a55f6ee8d8d6305057689a" +checksum = "b069d19bf01e46298eaedd7c6f283fe565a59263e53eebec945f3e6398f42390" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -1141,6 +1190,7 @@ checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ "axum-core", "bytes", + "form_urlencoded", "futures-util", "http 1.3.1", "http-body 1.0.1", @@ -1157,6 +1207,7 @@ dependencies = [ "serde", "serde_json", "serde_path_to_error", + "serde_urlencoded", "sync_wrapper", "tokio", "tower", @@ -1265,9 +1316,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" [[package]] name = "bitvec" @@ -1374,10 +1425,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.29" +version = "1.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -1400,6 +1453,46 @@ dependencies = [ "windows-link", ] +[[package]] +name = "clap" +version = "4.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + [[package]] name = "cmake" version = "0.1.54" @@ -1432,6 +1525,12 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "combine" version = "4.6.7" @@ -1533,9 +1632,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -1555,6 +1654,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -1616,7 +1725,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "synstructure", ] @@ -1641,7 +1750,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1652,7 +1761,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1724,7 +1833,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "unicode-xid", ] @@ -1757,7 +1866,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1780,9 +1889,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ecdsa" @@ -1847,7 +1956,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1932,6 +2041,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.2" @@ -2040,7 +2155,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -2081,9 +2196,9 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] name = "gcloud-sdk" -version = "0.27.3" +version = "0.27.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac903b34cd86b6e3479924e8a9517edba8d5deebee0c1013353b05108ea9bd3" +checksum = "c8458d2ad7741b6a16981b84e66b7e4d8026423096da721894769c6980d06ecc" dependencies = [ "async-trait", "bytes", @@ -2093,13 +2208,13 @@ dependencies = [ "jsonwebtoken", "once_cell", "prost 0.13.5", - "prost-types", + "prost-types 0.13.5", "reqwest", "secret-vault-value", "serde", "serde_json", "tokio", - "tonic", + "tonic 0.13.1", "tower", "tower-layer", "tower-util", @@ -2165,9 +2280,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "graph-gateway" @@ -2176,6 +2291,7 @@ dependencies = [ "anyhow", "assert_matches", "axum", + "base64", "custom_debug", "faster-hex", "futures", @@ -2194,19 +2310,20 @@ dependencies = [ "pin-project 1.1.10", "prometheus", "prost 0.14.1", - "rand 0.9.1", - "rdkafka", + "rand 0.9.2", + "rdkafka 0.38.0", "reqwest", "semver 1.0.26", "serde", "serde_json", "serde_with", "snmalloc-rs", + "tap_aggregator", "tap_graph", "thegraph-core", "thegraph-graphql-http", "thegraph-headers", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tokio-test", "tower", @@ -2250,9 +2367,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -2290,9 +2407,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -2380,9 +2497,9 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.1", + "rand 0.9.2", "ring", - "thiserror 2.0.12", + "thiserror 2.0.15", "tinyvec", "tokio", "tracing", @@ -2402,10 +2519,10 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.1", + "rand 0.9.2", "resolv-conf", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tracing", ] @@ -2568,9 +2685,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64", "bytes", @@ -2584,7 +2701,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "system-configuration", "tokio", "tower-service", @@ -2746,7 +2863,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -2776,17 +2893,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "serde", ] [[package]] name = "io-uring" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "cfg-if", "libc", ] @@ -2797,7 +2914,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -2825,6 +2942,12 @@ dependencies = [ "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -2849,6 +2972,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -2859,6 +2992,97 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpsee" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "jsonrpsee-types", + "parking_lot", + "pin-project 1.1.10", + "rand 0.9.2", + "rustc-hash", + "serde", + "serde_json", + "thiserror 2.0.15", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fa4f5daed39f982a1bb9d15449a28347490ad42b212f8eaa2a2a344a0dce9e9" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38b0bcf407ac68d241f90e2d46041e6a06988f97fe1721fb80b91c42584fae6" +dependencies = [ + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project 1.1.10", + "route-recognizer", + "serde", + "serde_json", + "soketto", + "thiserror 2.0.15", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" +dependencies = [ + "http 1.3.1", + "serde", + "serde_json", + "thiserror 2.0.15", +] + [[package]] name = "jsonwebtoken" version = "9.3.1" @@ -2915,9 +3139,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" @@ -2996,7 +3220,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -3007,7 +3231,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3095,6 +3319,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + [[package]] name = "native-tls" version = "0.2.14" @@ -3199,16 +3429,17 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "nybbles" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d51b0175c49668a033fe7cc69080110d9833b291566cdf332905f3ad9c68a0" +checksum = "63cb50036b1ad148038105af40aaa70ff24d8a14fbc44ae5c914e1348533d12e" dependencies = [ "alloy-rlp", + "cfg-if", "proptest", "ruint", "serde", @@ -3234,13 +3465,19 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "openssl" version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "cfg-if", "foreign-types", "libc", @@ -3257,7 +3494,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3334,7 +3571,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3404,10 +3641,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", - "thiserror 2.0.12", + "thiserror 2.0.15", "ucd-trie", ] +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap 2.10.0", +] + [[package]] name = "pin-project" version = "0.4.30" @@ -3445,7 +3692,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3506,6 +3753,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +dependencies = [ + "proc-macro2", + "syn 2.0.106", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -3545,14 +3802,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -3568,7 +3825,8 @@ dependencies = [ "lazy_static", "memchr", "parking_lot", - "thiserror 2.0.12", + "protobuf", + "thiserror 2.0.15", ] [[package]] @@ -3579,10 +3837,10 @@ checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.9.1", + "bitflags 2.9.2", "lazy_static", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax 0.8.5", @@ -3611,6 +3869,28 @@ dependencies = [ "prost-derive 0.14.1", ] +[[package]] +name = "prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" +dependencies = [ + "heck", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.14.1", + "prost-types 0.14.1", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.106", + "tempfile", +] + [[package]] name = "prost-derive" version = "0.13.5" @@ -3621,7 +3901,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3634,7 +3914,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3646,6 +3926,55 @@ dependencies = [ "prost 0.13.5", ] +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost 0.14.1", +] + +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags 2.9.2", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +dependencies = [ + "pulldown-cmark", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3687,9 +4016,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3744,6 +4073,44 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rdkafka" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b52c81ac3cac39c9639b95c20452076e74b8d9a71bc6fc4d83407af2ea6fff" +dependencies = [ + "futures-channel", + "futures-util", + "libc", + "log", + "rdkafka-sys", + "serde", + "serde_derive", + "serde_json", + "slab", + "tokio", +] + [[package]] name = "rdkafka" version = "0.38.0" @@ -3779,11 +4146,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", ] [[package]] @@ -3803,7 +4170,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3858,9 +4225,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.22" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "async-compression", "base64", @@ -3944,11 +4311,17 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + [[package]] name = "ruint" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +checksum = "9ecb38f82477f20c5c3d62ef52d7c4e536e38ea9b73fb570a20c5cae0e14bcf6" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -3963,7 +4336,7 @@ dependencies = [ "primitive-types", "proptest", "rand 0.8.5", - "rand 0.9.1", + "rand 0.9.2", "rlp", "ruint-macro", "serde", @@ -3989,9 +4362,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -4025,22 +4398,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.23.28" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -4059,7 +4432,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", + "security-framework 3.3.0", ] [[package]] @@ -4073,9 +4446,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -4084,9 +4457,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" @@ -4201,12 +4574,12 @@ dependencies = [ [[package]] name = "secret-vault-value" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc32a777b53b3433b974c9c26b6d502a50037f8da94e46cb8ce2ced2cfdfaea0" +checksum = "662c7f8e99d46c9d3a87561d771a970c29efaccbab4bbdc6ab65d099d2358077" dependencies = [ - "prost 0.13.5", - "prost-types", + "prost 0.14.1", + "prost-types 0.14.1", "serde", "serde_json", "zeroize", @@ -4218,7 +4591,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -4227,11 +4600,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4292,14 +4665,14 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -4358,7 +4731,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4462,9 +4835,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -4487,15 +4860,15 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.12", + "thiserror 2.0.15", "time", ] [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -4534,6 +4907,32 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "soketto" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" +dependencies = [ + "base64", + "bytes", + "futures", + "http 1.3.1", + "httparse", + "log", + "rand 0.8.5", + "sha1", +] + [[package]] name = "spki" version = "0.7.3" @@ -4564,24 +4963,23 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck", "proc-macro2", "quote", - "rustversion", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4603,9 +5001,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -4614,14 +5012,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ac494e7266fcdd2ad80bf4375d55d27a117ea5c866c26d0e97fe5b3caeeb75" +checksum = "a7a985ff4ffd7373e10e0fb048110fb11a162e5a4c47f92ddb8787a6f766b769" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4641,7 +5039,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4650,7 +5048,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4677,6 +5075,56 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tap_aggregator" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a883f8752e0054595101a9a1d069cf3238b101002bc66fce763dc5d121a179" +dependencies = [ + "anyhow", + "axum", + "clap", + "futures-util", + "hyper", + "jsonrpsee", + "lazy_static", + "log", + "prometheus", + "prost 0.14.1", + "rayon", + "rdkafka 0.37.0", + "serde", + "serde_json", + "strum", + "tap_core", + "tap_graph", + "thegraph-core", + "tokio", + "tonic 0.14.1", + "tonic-build", + "tonic-prost", + "tonic-prost-build", + "tower", + "tracing-subscriber", +] + +[[package]] +name = "tap_core" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c282c3989f6062ccc09b1bfb6032f742fc6243507b68b82b64e1d72aea330531" +dependencies = [ + "anyhow", + "async-trait", + "rand 0.9.2", + "tap_eip712_message", + "tap_graph", + "tap_receipt", + "thegraph-core", + "thiserror 2.0.15", + "tokio", +] + [[package]] name = "tap_eip712_message" version = "0.2.2" @@ -4685,7 +5133,7 @@ checksum = "e648d9aafebc6835d1bb50398452a82a237539a60d8cb02f3541c1e2d291fc39" dependencies = [ "serde", "thegraph-core", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] @@ -4694,7 +5142,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff0f8dd640afe0d3a53a6b6ae58f628f0f99267d33f61b7a1264daa9d4307003" dependencies = [ - "rand 0.9.1", + "rand 0.9.2", "serde", "tap_eip712_message", "tap_receipt", @@ -4713,7 +5161,7 @@ dependencies = [ "serde", "tap_eip712_message", "thegraph-core", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] @@ -4739,7 +5187,7 @@ dependencies = [ "bs58", "serde", "serde_with", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] @@ -4779,11 +5227,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.15", ] [[package]] @@ -4794,18 +5242,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4893,9 +5341,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.46.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", @@ -4906,9 +5354,9 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4919,7 +5367,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4969,12 +5417,13 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -5018,7 +5467,7 @@ dependencies = [ "pin-project 1.1.10", "prost 0.13.5", "rustls-native-certs", - "socket2", + "socket2 0.5.10", "tokio", "tokio-rustls", "tokio-stream", @@ -5028,6 +5477,75 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac5a8627ada0968acec063a4746bf79588aa03ccb66db2f75d7dce26722a40" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project 1.1.10", + "socket2 0.6.0", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", + "zstd", +] + +[[package]] +name = "tonic-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e323d8bba3be30833707e36d046deabf10a35ae8ad3cae576943ea8933e25d" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tonic-prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c511b9a96d40cb12b7d5d00464446acf3b9105fd3ce25437cfe41c92b1c87d" +dependencies = [ + "bytes", + "prost 0.14.1", + "tonic 0.14.1", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef298fcd01b15e135440c4b8c974460ceca4e6a5af7f1c933b08e4d2875efa1" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types 0.14.1", + "quote", + "syn 2.0.106", + "tempfile", + "tonic-build", +] + [[package]] name = "tower" version = "0.5.2" @@ -5053,7 +5571,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "bytes", "futures-util", "http 1.3.1", @@ -5122,7 +5640,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5135,18 +5653,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "futures", - "futures-task", - "pin-project 1.1.10", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -5267,11 +5773,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -5357,7 +5869,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "wasm-bindgen-shared", ] @@ -5392,7 +5904,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5525,7 +6037,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5536,7 +6048,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5617,7 +6129,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -5653,10 +6165,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -5816,9 +6329,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -5839,7 +6352,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", ] [[package]] @@ -5877,7 +6390,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "synstructure", ] @@ -5898,7 +6411,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5918,7 +6431,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "synstructure", ] @@ -5939,7 +6452,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5955,9 +6468,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -5972,5 +6485,33 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 4bc5a5b8..96e0ba7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ axum = { version = "0.8.1", default-features = false, features = [ "tokio", "http1", ] } +base64 = "0.22.1" custom_debug = "0.6.1" faster-hex = "0.10.0" futures = "0.3" @@ -46,8 +47,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0.116", features = ["raw_value"] } serde_with = "3.8.1" snmalloc-rs = "0.3" -tap_graph = "0.3.3" -thegraph-core = { version = "0.15", features = [ +tap_aggregator = "0.5.9" +tap_graph = { version = "0.3.4", features = ["v2"] } +thegraph-core = { version = "0.15.1", features = [ "alloy-contract", "alloy-signer-local", "attestation", diff --git a/Dockerfile b/Dockerfile index 48584f67..dc75b24f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y \ libsasl2-dev \ libssl-dev \ pkg-config \ + protobuf-compiler \ zlib1g-dev \ && rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index 01f13dcc..8c48b378 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ A gateway, in the Graph Network, is a client capable of managing relationships b data consumers and many indexers. A gateway is not necessary for a consumer to access the indexers participating in the Graph Network, though it does simplify consumer interactions. +**Note**: This is a horizon-ready gateway that generates TAP v2 (collection-based) receipts exclusively. It maintains backward compatibility for processing existing v1 (allocation-based) receipts. + A gateway is expected to be a reliable system, to compensate for indexers being relatively unreliable. Indexers may become unresponsive, malicious, or otherwise unsuitable for serving queries at any time without warning. It is the responsibility of the gateway to maintain the highest @@ -18,7 +20,7 @@ must have minimal impact on the primary responsibilities. ## indexer discovery For the gateway to route client queries to indexers, it must be able to associate subgraph and -subgraph deployment IDs with the indexers that have active allocations on the subgraph deployment +subgraph deployment IDs with the indexers that have active allocations or collections on the subgraph deployment being queried. The tree of subgraphs, subgraph deployments (versions), and allocated indexers is accessible via the network subgraph which indexes the Graph Network contracts. @@ -29,7 +31,7 @@ bootstrapping process for payments. When an indexer registers itself via the contract, it provides a URL to access its indexer-service. After the subgraph data is collected and organized, the gateway requests more information from each active indexer via the indexer-service. This includes software version information and, for each -allocation, the indexing status (progress on chain indexed by subgraph deployment) and cost models. +allocation or collection, the indexing status (progress on chain indexed by subgraph deployment) and cost models. The gateway may be configured to block public Proofs Of Indexing (POIs) that have been associated with bad query responses. In this case deployments with such POIs require an additional step in @@ -101,7 +103,7 @@ client query. Indexer fees are clamped to a maximum of the gateway's budget. For an overview of TAP see https://github.com/semiotic-ai/timeline-aggregation-protocol. -The gateway acts as a TAP sender, where each indexer request is sent with a TAP receipt. The gateway +The gateway acts as a TAP sender, where each indexer request is sent with a TAP v2 receipt. The gateway operator is expected to run 2 additional services: - [tap-aggregator](https://github.com/semiotic-ai/timeline-aggregation-protocol/tree/main/tap_aggregator): @@ -109,11 +111,12 @@ operator is expected to run 2 additional services: - [tap-escrow-manager](https://github.com/edgeandnode/tap-escrow-manager): maintains escrow balances for the TAP sender. This service requires data exported by the gateway into the "indexer requests" topic to calculate the value of outstanding receipts to each indexer. + For horizon compatibility, collection IDs are converted to addresses in the exported data. The gateway operator is also expected to manage at least 2 wallets: - sender: requires ETH for transaction gas and GRT to allocate into TAP escrow balances for paying indexers -- authorized signer: used by the gateway and tap-aggregator to sign receipts and RAVs +- authorized signer: used by the gateway and tap-aggregator to sign v2 receipts and RAVs ## operational notes diff --git a/src/client_query.rs b/src/client_query.rs index 281c69d7..575b3c38 100644 --- a/src/client_query.rs +++ b/src/client_query.rs @@ -19,7 +19,7 @@ use prost::bytes::Buf; use rand::Rng as _; use serde::Deserialize; use serde_json::value::RawValue; -use thegraph_core::{AllocationId, DeploymentId, IndexerId, alloy::primitives::BlockNumber}; +use thegraph_core::{CollectionId, DeploymentId, IndexerId, alloy::primitives::BlockNumber}; use thegraph_headers::{HttpBuilderExt as _, graph_attestation::GraphAttestation}; use tokio::sync::mpsc; use tracing::{Instrument as _, info_span}; @@ -61,9 +61,18 @@ pub async fn handle_query( ) -> Result, Error> { let start_time = Instant::now(); + // CRITICAL DEBUG: Log query entry point + tracing::warn!( + ?selector, + payload_length = payload.len(), + "QUERY ENTRY POINT - starting query processing" + ); + // Check if the query selector is authorized by the auth token and // resolve the subgraph deployments for the query. + tracing::debug!("about to call resolve_subgraph_info"); let subgraph = resolve_subgraph_info(&ctx, &auth, selector).await?; + tracing::debug!("resolve_subgraph_info completed successfully"); let client_request: QueryBody = serde_json::from_reader(payload.reader()).map_err(|err| Error::BadQuery(err.into()))?; @@ -167,6 +176,72 @@ async fn resolve_subgraph_info( } } +/// Executes a GraphQL query across multiple indexers in the Graph Network. +/// +/// This is the core orchestration function that handles the complete query lifecycle: +/// indexer selection, concurrent query execution, TAP payment processing, and response aggregation. +/// +/// # Arguments +/// +/// * `ctx` - Gateway context containing shared services (indexer client, network state, etc.) +/// * `request_id` - Unique identifier for this request used in tracing and reporting +/// * `auth` - Authenticated user settings including API key and authorized subgraphs +/// * `start_time` - Query start timestamp for latency calculations +/// * `subgraph` - Resolved subgraph information including available indexers and deployments +/// * `budget` - Maximum query budget in GRT smallest units (1 GRT = 10^18 units) +/// * `client_request` - Original GraphQL query and variables from the client +/// * `client_response` - Channel to send the first successful response back to the client +/// +/// # Behavior +/// +/// The function implements a multi-round retry strategy: +/// +/// 1. **Query Parsing**: Validates GraphQL syntax and creates execution context +/// 2. **Chain State**: Resolves current chain head and block requirements from query +/// 3. **Candidate Selection**: Filters available indexers by performance, block range, and availability +/// 4. **Concurrent Execution**: Selects up to 3 indexers per round and queries them simultaneously +/// 5. **First Success Wins**: Returns the first successful response to the client immediately +/// 6. **Retry Logic**: If all indexers fail, removes failed candidates and retries with remaining indexers +/// 7. **Comprehensive Reporting**: Exports all request data to Kafka regardless of success/failure +/// +/// # Payment Processing +/// +/// Each indexer request includes a cryptographically signed TAP receipt: +/// - Dynamic fee calculation based on budget and indexer count +/// - EIP-712 signed receipt with allocation ID, timestamp, nonce, and fee amount +/// - Budget feedback to dynamic pricing controller +/// +/// # Error Handling +/// +/// - **Query Errors**: Malformed GraphQL returns `Error::BadQuery` +/// - **No Indexers**: All indexers filtered out returns `Error::NoIndexers` +/// - **All Failed**: All indexers failed returns `Error::BadIndexers` with detailed error map +/// - **Timeout**: 60-second timeout with best available error response +/// +/// # Performance Characteristics +/// +/// - **Latency**: Optimized for first successful response (typically 100-500ms) +/// - **Fault Tolerance**: Multiple indexer selection with automatic failover +/// - **Concurrency**: All selected indexers queried simultaneously +/// - **Monitoring**: Comprehensive metrics and tracing for observability +/// +/// # Side Effects +/// +/// - Updates indexer performance metrics based on response times and success rates +/// - Sends budget feedback for dynamic pricing adjustments +/// - Exports complete request data to Kafka topics for analytics +/// - Updates chain head information from indexer responses +/// +/// # Example Flow +/// +/// ```text +/// Client Query → Parse GraphQL → Select 3 Indexers → Concurrent Requests +/// ↓ +/// First Success ← Client Response ← TAP Receipts ← Indexer Responses +/// ↓ +/// Kafka Export ← Performance Updates ← Budget Feedback ← Error Tracking +/// ``` +/// #[allow(clippy::too_many_arguments)] async fn run_indexer_queries( ctx: Context, @@ -265,6 +340,10 @@ async fn run_indexer_queries( // all the available indexers in the `bad indexers` response. while !candidates.is_empty() && (start_time.elapsed() < Duration::from_secs(60)) { let selections: ArrayVec<_, SELECTION_LIMIT> = indexer_selection::select(&candidates); + tracing::debug!( + selections_count = selections.len(), + "indexer_selection returned selections" + ); if selections.is_empty() { // Candidates that would never be selected should be filtered out for improved errors. tracing::error!("no candidates selected"); @@ -273,10 +352,16 @@ async fn run_indexer_queries( let (tx, mut rx) = mpsc::channel(SELECTION_LIMIT); let min_fee = *ctx.budgeter.min_indexer_fees.borrow(); + tracing::debug!( + selections_count = selections.len(), + ?min_fee, + budget, + "about to process selections for receipt creation" + ); for &selection in &selections { let indexer = selection.id; let deployment = selection.data.deployment; - let largest_allocation = selection.data.largest_allocation; + let largest_collection = selection.data.largest_collection; let url = selection.data.url.clone(); let seconds_behind = selection.seconds_behind; let subgraph_chain = subgraph.chain.clone(); @@ -285,8 +370,30 @@ async fn run_indexer_queries( let min_fee = *(min_fee.0 * grt_per_usd * one_grt) / selections.len() as f64; let indexer_fee = selection.fee.as_f64() * budget as f64; let fee = indexer_fee.max(min_fee) as u128; - let receipt = match ctx.receipt_signer.create_receipt(largest_allocation, fee) { - Ok(receipt) => receipt, + tracing::debug!( + ?indexer, + ?largest_collection, + fee, + indexer_fee, + min_fee, + "processing indexer for receipt creation" + ); + let receipt = match ctx.receipt_signer.create_receipt( + largest_collection, + fee, + ctx.receipt_signer.payer_address(), // payer: gateway address + ctx.receipt_signer.payer_address(), // data_service: gateway address + indexer.into_inner(), // service_provider: indexer address + ) { + Ok(receipt) => { + tracing::debug!( + ?indexer, + fee, + receipt_value = receipt.value(), + "successfully created TAP receipt" + ); + receipt + } Err(err) => { tracing::error!(?indexer, %deployment, error=?err, "failed to create receipt"); continue; @@ -304,6 +411,11 @@ async fn run_indexer_queries( // URL checked: ref df8e647b-1e6e-422a-8846-dc9ee7e0dcc2 let deployment_url = url.join(&format!("subgraphs/id/{deployment}")).unwrap(); let auth = IndexerAuth::Paid(&receipt, ctx.attestation_domain); + tracing::debug!( + ?indexer, + receipt_value = receipt.value(), + "querying indexer with Paid auth" + ); let result = indexer_client .query_indexer(deployment_url, auth, &indexer_query) .in_current_span() @@ -412,7 +524,7 @@ async fn run_indexer_queries( tracing::info!( indexer = ?indexer_request.indexer, deployment = %indexer_request.deployment, - allocation = ?indexer_request.receipt.allocation(), + collection = ?indexer_request.receipt.collection(), url = indexer_request.url, result = ?indexer_request.result.as_ref().map(|_| ()), response_time_ms = indexer_request.response_time_ms, @@ -463,7 +575,7 @@ struct CandidateMetadata { deployment: DeploymentId, #[debug(with = std::fmt::Display::fmt)] url: Url, - largest_allocation: AllocationId, + largest_collection: CollectionId, } /// Given a list of indexings, build a list of candidates that are within the required block range @@ -571,7 +683,7 @@ fn build_candidates_list( data: CandidateMetadata { deployment, url: indexing.indexer.url.clone(), - largest_allocation: indexing.largest_allocation, + largest_collection: indexing.largest_collection, }, perf: perf.response, fee: Normalized::new(indexing.fee as f64 / budget as f64).unwrap_or(Normalized::ONE), @@ -681,8 +793,14 @@ pub async fn handle_indexer_query( let one_grt = NotNan::new(1e18).unwrap(); let fee = *(ctx.budgeter.query_fees_target.0 * grt_per_usd * one_grt) as u128; - let allocation = indexing.largest_allocation; - let receipt = match ctx.receipt_signer.create_receipt(allocation, fee) { + let collection = indexing.largest_collection; + let receipt = match ctx.receipt_signer.create_receipt( + collection, + fee, + ctx.receipt_signer.payer_address(), // payer: gateway address + ctx.receipt_signer.payer_address(), // data_service: gateway address + indexer.into_inner(), // service_provider: indexer address + ) { Ok(receipt) => receipt, Err(err) => { return Err(Error::Internal(anyhow!("failed to create receipt: {err}"))); @@ -744,7 +862,7 @@ pub async fn handle_indexer_query( tracing::info!( indexer = ?indexer_request.indexer, deployment = %indexer_request.deployment, - allocation = ?indexer_request.receipt.allocation(), + collection = ?indexer_request.receipt.collection(), url = indexer_request.url, result = ?indexer_request.result.as_ref().map(|_| ()), response_time_ms = indexer_request.response_time_ms, diff --git a/src/config.rs b/src/config.rs index 49a9e498..9c0691dd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -46,8 +46,11 @@ pub struct Config { /// Minimum indexer-service version that will receive queries #[serde_as(as = "DisplayFromStr")] pub min_indexer_version: Version, - /// Indexers used to query the network subgraph + /// Trusted indexers that can serve the network subgraph for free pub trusted_indexers: Vec, + /// Maximum acceptable lag (in seconds) for network subgraph responses (default: 120) + #[serde(default = "default_network_subgraph_max_lag_seconds")] + pub network_subgraph_max_lag_seconds: u64, /// Check payment state of client (disable for testnets) pub payment_required: bool, /// public API port @@ -60,6 +63,11 @@ pub struct Config { pub receipts: Receipts, } +/// Default network subgraph max lag threshold (120 seconds) +fn default_network_subgraph_max_lag_seconds() -> u64 { + 120 +} + /// Deserialize a `NotNan` from a `f64` and return an error if the value is NaN. fn deserialize_not_nan_f64<'de, D>(deserializer: D) -> Result, D::Error> where diff --git a/src/indexer_client.rs b/src/indexer_client.rs index b6d27944..c065974e 100644 --- a/src/indexer_client.rs +++ b/src/indexer_client.rs @@ -47,13 +47,31 @@ impl IndexerClient { query: &str, ) -> Result { let (auth_key, auth_value) = match auth { - IndexerAuth::Paid(receipt, _) => ("Tap-Receipt", receipt.serialize()), + IndexerAuth::Paid(receipt, _) => ("tap-receipt", receipt.serialize()), IndexerAuth::Free(token) => (AUTHORIZATION.as_str(), format!("Bearer {token}")), }; + // Debug logging to track actual HTTP request details + tracing::debug!( + url = %deployment_url, + auth_header = auth_key, + auth_value_length = auth_value.len(), + query_length = query.len(), + "sending HTTP POST request to indexer" + ); + + // CRITICAL DEBUG: Log if TAP receipt header is being set + if auth_key == "tap-receipt" { + tracing::warn!( + url = %deployment_url, + auth_value_preview = &auth_value[..auth_value.len().min(50)], + "TAP RECEIPT HEADER BEING SENT TO INDEXER" + ); + } + let result = self .client - .post(deployment_url) + .post(deployment_url.clone()) .header(CONTENT_TYPE.as_str(), "application/json") .header(auth_key, auth_value) .body(query.to_string()) @@ -116,11 +134,11 @@ impl IndexerClient { if let IndexerAuth::Paid(receipt, attestation_domain) = auth { match &payload.attestation { Some(attestation) => { - let allocation = receipt.allocation(); + let collection = receipt.collection(); if let Err(err) = attestation::verify( attestation_domain, attestation, - &allocation, + &collection.as_address(), query, &original_response, ) { diff --git a/src/main.rs b/src/main.rs index 7485f31c..aaf12ed8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,6 +112,7 @@ async fn main() { indexers: conf.trusted_indexers, latest_block: None, page_size: 500, + max_lag_seconds: conf.network_subgraph_max_lag_seconds, }; let indexer_host_blocklist = match &conf.ip_blocker_db { Some(path) => { diff --git a/src/middleware/legacy_auth.rs b/src/middleware/legacy_auth.rs index 8ce6c22c..c76f34b0 100644 --- a/src/middleware/legacy_auth.rs +++ b/src/middleware/legacy_auth.rs @@ -22,12 +22,12 @@ pub async fn legacy_auth_adapter(mut request: Request, next: Next) -> Response>>().await { - if let Some(api_key) = path.get("api_key") { - parts - .headers - .typed_insert(Authorization::bearer(api_key).expect("valid api_key")); - } + if let Ok(Path(path)) = parts.extract::>>().await + && let Some(api_key) = path.get("api_key") + { + parts + .headers + .typed_insert(Authorization::bearer(api_key).expect("valid api_key")); } // reconstruct the request diff --git a/src/network/indexer_processing.rs b/src/network/indexer_processing.rs index 700e3d6f..3be0a9f7 100644 --- a/src/network/indexer_processing.rs +++ b/src/network/indexer_processing.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use custom_debug::CustomDebug; -use thegraph_core::{AllocationId, DeploymentId, IndexerId, alloy::primitives::BlockNumber}; +use thegraph_core::{CollectionId, DeploymentId, IndexerId, alloy::primitives::BlockNumber}; use tracing::Instrument; use url::Url; @@ -52,8 +52,8 @@ pub struct IndexerInfo { /// This is not the final representation of the indexer's indexing information. #[derive(Clone, Debug, Eq, PartialEq)] pub struct IndexingRawInfo { - /// The largest allocation. - pub largest_allocation: AllocationId, + /// The largest collection (V2 Horizon). + pub largest_collection: CollectionId, } /// Internal representation of the fetched indexer's indexing information. @@ -62,8 +62,8 @@ pub struct IndexingRawInfo { /// information: unresolved, partially resolved (with indexing progress) and completely resolved. #[derive(Debug)] pub struct IndexingInfo { - /// The largest allocation. - pub largest_allocation: AllocationId, + /// The largest collection (V2 Horizon). + pub largest_collection: CollectionId, /// The indexing progress information /// @@ -77,7 +77,7 @@ pub struct IndexingInfo { impl From for IndexingInfo<(), ()> { fn from(raw: IndexingRawInfo) -> Self { Self { - largest_allocation: raw.largest_allocation, + largest_collection: raw.largest_collection, progress: (), fee: (), } @@ -92,7 +92,7 @@ impl IndexingInfo<(), ()> { progress: IndexingProgress, ) -> IndexingInfo { IndexingInfo { - largest_allocation: self.largest_allocation, + largest_collection: self.largest_collection, progress, fee: self.fee, } @@ -104,7 +104,7 @@ impl IndexingInfo { /// state by adding the cost model to the indexing information. fn with_fee(self, fee: u128) -> IndexingInfo { IndexingInfo { - largest_allocation: self.largest_allocation, + largest_collection: self.largest_collection, progress: self.progress, fee, } diff --git a/src/network/pre_processing.rs b/src/network/pre_processing.rs index dc7b64a3..4bbd2962 100644 --- a/src/network/pre_processing.rs +++ b/src/network/pre_processing.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, hash_map::Entry}; use anyhow::{anyhow, ensure}; -use thegraph_core::{AllocationId, DeploymentId, IndexerId, SubgraphId}; +use thegraph_core::{CollectionId, DeploymentId, IndexerId, SubgraphId}; use url::Url; use crate::network::{ @@ -16,9 +16,9 @@ use crate::network::{ pub fn into_internal_indexers_raw_info<'a>( data: impl Iterator, ) -> HashMap { - let mut indexer_indexing_largest_allocation: HashMap< + let mut indexer_indexing_largest_collection: HashMap< (IndexerId, DeploymentId), - (AllocationId, u128), + (CollectionId, u128), > = HashMap::new(); data.flat_map(|subgraph| { @@ -28,14 +28,14 @@ pub fn into_internal_indexers_raw_info<'a>( .map(|version| (&subgraph.id, version)) }) .fold(HashMap::new(), |mut acc, (subgraph_id, version)| { - for allocation in &version.subgraph_deployment.allocations { - let indexer_id = allocation.indexer.id; + for payments_escrow in &version.subgraph_deployment.payments_escrows { + let indexer_id = payments_escrow.indexer.id; let deployment_id = version.subgraph_deployment.id; // If the indexer info is not present, insert it if it is valid let indexer = match acc.entry(indexer_id) { Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => match try_into_indexer_raw_info(&allocation.indexer) { + Entry::Vacant(entry) => match try_into_indexer_raw_info(&payments_escrow.indexer) { Ok(info) => entry.insert(info), Err(err) => { // Log the error and skip the indexer @@ -43,7 +43,7 @@ pub fn into_internal_indexers_raw_info<'a>( subgraph_id=%subgraph_id, version=%version.version, deployment_id=%deployment_id, - allocation_id=%allocation.id, + payments_escrow_id=%payments_escrow.id, indexer_id=%indexer_id, "invalid indexer info: {err}" ); @@ -52,21 +52,41 @@ pub fn into_internal_indexers_raw_info<'a>( }, }; - // Update the indexer's indexings largest allocations table - let indexing_largest_allocation = match indexer_indexing_largest_allocation + // Update the indexer's indexings largest collections table (V2 escrow-based) + // Find the largest collection from this payments escrow + let largest_collection_id = payments_escrow + .collections + .first() // Use first collection (V2 equivalent of largest allocation) + .map(|c| { + // Log collection status for monitoring + tracing::trace!(collection_id = %c.id, status = %c.status, "processing collection"); + c.id + }) + .unwrap_or_else(|| { + // Fallback: create a collection ID from payments escrow ID for compatibility + use thegraph_core::{CollectionId, alloy::primitives::FixedBytes}; + // This is a temporary compatibility layer - create a collection ID from the escrow ID + let mut bytes = [0u8; 32]; + let escrow_bytes = payments_escrow.id.as_bytes(); + let copy_len = escrow_bytes.len().min(32); + bytes[..copy_len].copy_from_slice(&escrow_bytes[..copy_len]); + CollectionId::new(FixedBytes::from(bytes)) + }); + + let indexing_largest_collection = match indexer_indexing_largest_collection .entry((indexer_id, deployment_id)) { Entry::Vacant(entry) => { - entry.insert((allocation.id, allocation.allocated_tokens)); - allocation.id + entry.insert((largest_collection_id, payments_escrow.balance)); + largest_collection_id } Entry::Occupied(entry) => { - let (largest_allocation_address, largest_allocation_amount) = entry.into_mut(); - if allocation.allocated_tokens > *largest_allocation_amount { - *largest_allocation_address = allocation.id; - *largest_allocation_amount = allocation.allocated_tokens; + let (largest_collection_id_ref, largest_collection_amount) = entry.into_mut(); + if payments_escrow.balance > *largest_collection_amount { + *largest_collection_id_ref = largest_collection_id; + *largest_collection_amount = payments_escrow.balance; } - *largest_allocation_address + *largest_collection_id_ref } }; @@ -75,10 +95,10 @@ pub fn into_internal_indexers_raw_info<'a>( .indexings .entry(deployment_id) .or_insert(IndexingRawInfo { - largest_allocation: allocation.id, + largest_collection: largest_collection_id, }); - indexing.largest_allocation = indexing_largest_allocation; + indexing.largest_collection = indexing_largest_collection; } acc @@ -122,10 +142,19 @@ pub fn into_internal_deployments_raw_info<'a>( .fold(HashMap::new(), |mut acc, deployment_raw_info| { let deployment_id = deployment_raw_info.id; + // Debug logging for deployment processing + tracing::debug!( + ?deployment_id, + subgraphs_count = deployment_raw_info.subgraphs.len(), + allocations_count = deployment_raw_info.allocations.len(), + "processing deployment in pre_processing pipeline" + ); + // If the deployment info is not present, insert it let deployment = match acc.entry(deployment_id) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => { + tracing::debug!(?deployment_id, "inserting new deployment into registry"); entry.insert(deployment_raw_info.clone()); return acc; } @@ -136,9 +165,9 @@ pub fn into_internal_deployments_raw_info<'a>( .subgraphs .extend(deployment_raw_info.subgraphs.iter().cloned()); - // Merge the associated allocations + // Merge the associated indexer allocations (derived from V2 payments escrows) deployment - .allocations + .allocations // Field name preserved for compatibility with existing processing pipeline .extend(deployment_raw_info.allocations.iter().cloned()); acc @@ -180,10 +209,10 @@ fn into_subgraph_version_raw_info( let deployment = version.subgraph_deployment; let deployment_allocations = deployment - .allocations + .payments_escrows .into_iter() - .map(|allocation| AllocationInfo { - indexer: allocation.indexer.id, + .map(|payments_escrow| AllocationInfo { + indexer: payments_escrow.indexer.id, }) .collect::>(); diff --git a/src/network/service.rs b/src/network/service.rs index 06d70f07..6b2e644c 100644 --- a/src/network/service.rs +++ b/src/network/service.rs @@ -128,9 +128,24 @@ impl NetworkService { ) -> Result, DeploymentError> { let network = self.network.borrow(); + // Debug logging for deployment resolution + tracing::debug!( + ?id, + total_deployments = network.deployments.len(), + "attempting to resolve deployment ID" + ); + + // Log first few deployment IDs for comparison + for (dep_id, _) in network.deployments.iter().take(3) { + tracing::debug!(?dep_id, "available deployment in registry"); + } + // Resolve the deployment information let deployment = match network.deployments.get(id) { - None => return Ok(None), + None => { + tracing::warn!(?id, "deployment ID not found in registry"); + return Ok(None); + } Some(Err(err)) => return Err(err.to_owned()), Some(Ok(deployment)) => deployment, }; diff --git a/src/network/snapshot.rs b/src/network/snapshot.rs index 3ee43ec8..89c23a12 100644 --- a/src/network/snapshot.rs +++ b/src/network/snapshot.rs @@ -6,7 +6,7 @@ use std::{ use custom_debug::CustomDebug; use thegraph_core::{ - AllocationId, DeploymentId, IndexerId, SubgraphId, alloy::primitives::BlockNumber, + CollectionId, DeploymentId, IndexerId, SubgraphId, alloy::primitives::BlockNumber, }; use url::Url; @@ -35,7 +35,7 @@ pub struct Indexing { /// /// This is, among all allocations associated with the indexer and deployment, the address /// with the largest amount of allocated tokens. - pub largest_allocation: AllocationId, + pub largest_collection: CollectionId, /// The indexer pub indexer: Arc, /// The indexing progress. @@ -358,13 +358,13 @@ fn construct_indexings_table_row( }; // Construct the indexing table row - let indexing_largest_allocation_addr = indexing_info.largest_allocation; + let indexing_largest_collection_id = indexing_info.largest_collection; let indexing_progress = indexing_info.progress.to_owned(); let fee = indexing_info.fee; let indexing = Indexing { id: indexing_id, - largest_allocation: indexing_largest_allocation_addr, + largest_collection: indexing_largest_collection_id, indexer: Arc::clone(indexer), progress: IndexingProgress { latest_block: indexing_progress.latest_block, diff --git a/src/network/subgraph_client.rs b/src/network/subgraph_client.rs index 1bd218e8..89673271 100644 --- a/src/network/subgraph_client.rs +++ b/src/network/subgraph_client.rs @@ -34,13 +34,20 @@ pub mod types { use serde::Deserialize; use serde_with::serde_as; use thegraph_core::{ - AllocationId, DeploymentId, IndexerId, SubgraphId, alloy::primitives::BlockNumber, + CollectionId, DeploymentId, IndexerId, SubgraphId, alloy::primitives::BlockNumber, }; #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Subgraph { pub id: SubgraphId, + // V2 Horizon fields (populated programmatically, not from JSON) + #[serde(skip)] + pub _service_provider: Option, + #[serde(skip)] + pub _allocations: Vec, + // V1 compatibility (for gradual migration) + #[serde(default)] pub versions: Vec, } @@ -66,18 +73,57 @@ pub mod types { #[serde(rename = "ipfsHash")] pub id: DeploymentId, pub manifest: Option, - #[serde(rename = "indexerAllocations")] - pub allocations: Vec, + #[serde(default)] + pub payments_escrows: Vec, } #[serde_as] #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] - pub struct Allocation { - pub id: AllocationId, + pub struct PaymentsEscrow { + pub id: String, #[serde_as(as = "serde_with::DisplayFromStr")] - pub allocated_tokens: u128, + pub balance: u128, pub indexer: Indexer, + pub collections: Vec, + pub _subgraph_deployment: SubgraphDeployment, + } + + #[derive(Debug, Clone, Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct Collection { + pub id: CollectionId, + pub status: String, + } + + #[derive(Debug, Clone, Deserialize)] + pub struct ServiceProvider { + pub _id: IndexerId, + pub _url: Option, + #[serde(rename = "stakedTokens")] + pub _staked_tokens: String, + } + + #[derive(Debug, Clone, Deserialize)] + pub struct ServiceAllocation { + pub _id: String, + pub _tokens: String, + #[serde(rename = "subgraphDeployment")] + pub _subgraph_deployment: DeploymentInfo, + } + + #[derive(Debug, Clone, Deserialize)] + pub struct DeploymentInfo { + #[serde(rename = "ipfsHash")] + pub _ipfs_hash: DeploymentId, + pub _manifest: Option, + } + + #[derive(Debug, Clone, Deserialize)] + pub struct ManifestInfo { + pub _network: Option, + #[serde(rename = "startBlock")] + pub _start_block: String, } #[serde_as] @@ -94,7 +140,7 @@ pub mod types { #[serde_as] #[derive(Clone, CustomDebug, Deserialize)] pub struct TrustedIndexer { - /// network subgraph endpoint + /// Complete network subgraph endpoint URL (e.g., http://indexer:7601/subgraphs/id/Qmc2Cb...) #[debug(with = std::fmt::Display::fmt)] #[serde_as(as = "serde_with::DisplayFromStr")] pub url: Url, @@ -125,6 +171,7 @@ pub struct Client { pub indexers: Vec, pub page_size: usize, pub latest_block: Option, + pub max_lag_seconds: u64, } impl Client { @@ -152,31 +199,23 @@ impl Client { let query = r#" query ($block: Block_height!, $first: Int!, $last: String!) { meta: _meta(block: $block) { block { number hash timestamp } } - results: subgraphs( + subgraphs( block: $block - orderBy: id, orderDirection: asc first: $first - where: { - id_gt: $last - entityVersion: 2 - versionCount_gte: 1 - active: true - } + orderBy: id, orderDirection: asc + where: { id_gt: $last } ) { id - versions(orderBy: version, orderDirection: desc) { + versions { version subgraphDeployment { + id ipfsHash manifest { network startBlock } - indexerAllocations( - first: 100 - orderBy: allocatedTokens, orderDirection: desc - where: { status: Active } - ) { + indexerAllocations { id allocatedTokens indexer { @@ -199,7 +238,60 @@ impl Client { #[derive(Debug, Deserialize)] pub struct QueryData { meta: Meta, - results: Vec, + subgraphs: Vec, + } + + #[derive(Debug, Deserialize)] + pub struct SubgraphWithVersions { + pub id: String, + pub versions: Vec, + } + + #[derive(Debug, Deserialize)] + pub struct SubgraphVersionWithDeployment { + pub version: u32, + #[serde(rename = "subgraphDeployment")] + pub subgraph_deployment: DeploymentWithAllocations, + } + + #[derive(Debug, Deserialize)] + pub struct DeploymentWithAllocations { + pub id: String, + #[serde(rename = "ipfsHash")] + pub ipfs_hash: String, + pub manifest: Option, + #[serde(rename = "indexerAllocations")] + pub indexer_allocations: Vec, + } + + #[derive(Debug, Deserialize)] + pub struct AllocationWithIndexer { + pub id: String, + #[serde(rename = "allocatedTokens")] + pub allocated_tokens: String, + pub indexer: IndexerInfo, + } + + #[derive(Debug, Deserialize)] + pub struct IndexerInfo { + pub id: thegraph_core::IndexerId, + pub url: Option, + #[serde(rename = "stakedTokens")] + pub staked_tokens: String, + } + + #[derive(Debug, Deserialize)] + pub struct DeploymentInfo { + #[serde(rename = "ipfsHash")] + pub _ipfs_hash: thegraph_core::DeploymentId, + pub _manifest: Option, + } + + #[derive(Debug, Deserialize)] + pub struct ManifestInfo { + pub network: String, + #[serde(rename = "startBlock")] + pub start_block: String, } #[derive(Debug, Deserialize)] pub struct Meta { @@ -232,10 +324,19 @@ impl Client { "last": last_id.unwrap_or_default(), }, }); + // Use trusted indexer URL directly - it already contains the complete network subgraph endpoint + let network_subgraph_url = indexer.url.clone(); + + // Debug logging for network subgraph URL usage + tracing::debug!( + network_subgraph_url = %network_subgraph_url, + "using trusted indexer URL for network subgraph query" + ); + let response = self .client .query_indexer( - indexer.url.clone(), + network_subgraph_url, IndexerAuth::Free(&indexer.auth), &page_query.to_string(), ) @@ -250,7 +351,7 @@ impl Client { if !response.errors.is_empty() { bail!("{:?}", response.errors); } - let mut data = response + let data = response .data .ok_or_else(|| anyhow!("response missing data"))?; let block = Block { @@ -271,14 +372,111 @@ impl Client { "response block before latest", ); ensure!( - (unix_timestamp() / 1_000).saturating_sub(block.timestamp) < 120, + (unix_timestamp() / 1_000).saturating_sub(block.timestamp) + < self.max_lag_seconds, "response too far behind", ); query_block = Some(block); } - last_id = data.results.last().map(|entry| entry.id.to_string()); - let page_len = data.results.len(); - results.append(&mut data.results); + // Process V2 subgraphs data with correct SubgraphId → DeploymentId mapping + let subgraphs = data.subgraphs; + last_id = subgraphs.last().map(|entry| entry.id.clone()); + let page_len = subgraphs.len(); + + results.extend(subgraphs.into_iter().map(|subgraph| { + // Parse the SubgraphId from the response + let subgraph_id = subgraph + .id + .parse::() + .unwrap_or_else(|_| { + // Fallback: create SubgraphId from string bytes + use thegraph_core::{SubgraphId, alloy::primitives::FixedBytes}; + let mut bytes = [0u8; 32]; + let id_bytes = subgraph.id.as_bytes(); + let copy_len = id_bytes.len().min(32); + bytes[..copy_len].copy_from_slice(&id_bytes[..copy_len]); + SubgraphId::new(FixedBytes::from(bytes)) + }); + + types::Subgraph { + id: subgraph_id, + _service_provider: None, // V2 doesn't use service providers + _allocations: Vec::new(), // V2 data structure doesn't populate this + versions: subgraph + .versions + .into_iter() + .map(|version| { + // Log deployment info for debugging + tracing::debug!( + deployment_id = %version.subgraph_deployment.id, + ipfs_hash = %version.subgraph_deployment.ipfs_hash, + "processing V2 subgraph deployment" + ); + + let deployment_id = version + .subgraph_deployment + .ipfs_hash + .parse::() + .expect("V2 IPFS hash should be valid DeploymentId"); + + types::SubgraphVersion { + version: version.version, + subgraph_deployment: types::SubgraphDeployment { + id: deployment_id, + manifest: version.subgraph_deployment.manifest.map(|m| { + types::Manifest { + network: Some(m.network), + start_block: m.start_block.parse().unwrap_or(0), + } + }), + payments_escrows: version + .subgraph_deployment + .indexer_allocations + .into_iter() + .map(|alloc| { + let allocation_id = alloc.id.clone(); + types::PaymentsEscrow { + id: alloc.id, + balance: alloc + .allocated_tokens + .parse() + .unwrap_or(0), + indexer: types::Indexer { + id: alloc.indexer.id, + url: alloc.indexer.url, + staked_tokens: alloc + .indexer + .staked_tokens + .parse() + .unwrap_or(0), + }, + collections: vec![types::Collection { + id: { + // Convert allocation ID to collection ID using standard left-padding + use thegraph_core::AllocationId; + let allocation_parsed = allocation_id + .parse::() + .expect( + "V2 allocation ID should be valid", + ); + allocation_parsed.into() // Uses standard left-padding conversion + }, + status: "Active".to_string(), // Default status + }], + _subgraph_deployment: types::SubgraphDeployment { + id: deployment_id, + manifest: None, // Avoid circular reference + payments_escrows: Vec::new(), // Avoid circular reference + }, + } + }) + .collect(), + }, + } + }) + .collect(), + } + })); if page_len < self.page_size { break; } diff --git a/src/receipts.rs b/src/receipts.rs index 63dc333a..7872423a 100644 --- a/src/receipts.rs +++ b/src/receipts.rs @@ -1,9 +1,11 @@ use std::time::SystemTime; +use base64::{Engine as _, engine::general_purpose}; +use prost::Message; use rand::RngCore; -use tap_graph::{Receipt as TapReceipt, SignedReceipt}; +use serde::Serialize; use thegraph_core::{ - AllocationId, + CollectionId, alloy::{ dyn_abi::Eip712Domain, primitives::{Address, U256}, @@ -11,47 +13,92 @@ use thegraph_core::{ }, }; -pub struct Receipt(SignedReceipt); +/// TAP v2 receipts for the Horizon upgrade +/// +/// This gateway only generates and processes v2 receipts (collection-based) +#[derive(Debug, Clone)] +pub struct Receipt(pub tap_graph::v2::SignedReceipt); impl Receipt { + /// Get the fee value from the receipt pub fn value(&self) -> u128 { self.0.message.value } - pub fn allocation(&self) -> Address { - self.0.message.allocation_id + /// Get the collection identifier + pub fn collection(&self) -> CollectionId { + self.0.message.collection_id.into() } + /// Serialize the receipt to base64-encoded protobuf format for V2 compatibility pub fn serialize(&self) -> String { - serde_json::to_string(&self.0).unwrap() + // Convert tap_graph::v2::SignedReceipt to protobuf format + let protobuf_receipt: tap_aggregator::grpc::v2::SignedReceipt = self.0.clone().into(); + + // Encode to protobuf bytes + let bytes = protobuf_receipt.encode_to_vec(); + + // Base64 encode the bytes + let serialized = general_purpose::STANDARD.encode(&bytes); + + // DEBUG: Log receipt serialization details + tracing::debug!( + serialized_preview = &serialized[..serialized.len().min(100)], + serialized_length = serialized.len(), + protobuf_bytes_length = bytes.len(), + "TAP receipt serialized format" + ); + + serialized + } +} + +impl Serialize for Receipt { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) } } +/// Configuration for receipt creation +#[derive(Debug, Clone)] +pub struct ReceiptConfig { + pub domain: Eip712Domain, +} + pub struct ReceiptSigner { signer: PrivateKeySigner, - domain: Eip712Domain, + v2_config: ReceiptConfig, } impl ReceiptSigner { pub fn new(signer: PrivateKeySigner, chain_id: U256, verifying_contract: Address) -> Self { + let v2_domain = Eip712Domain { + name: Some("TAP".into()), + version: Some("2".into()), + chain_id: Some(chain_id), + verifying_contract: Some(verifying_contract), + salt: None, + }; + Self { signer, - domain: Eip712Domain { - name: Some("TAP".into()), - version: Some("1".into()), - chain_id: Some(chain_id), - verifying_contract: Some(verifying_contract), - salt: None, - }, + v2_config: ReceiptConfig { domain: v2_domain }, } } - pub fn create_receipt(&self, allocation: AllocationId, fee: u128) -> anyhow::Result { - // Nonce generated with CSPRNG (ChaCha12), to avoid collision with receipts generated by - // other gateway processes. - // See https://docs.rs/rand/latest/rand/rngs/index.html#our-generators. + /// Create a v2 receipt (collection-based) - ONLY method for generating receipts + pub fn create_receipt( + &self, + collection: CollectionId, + fee: u128, + payer: Address, + data_service: Address, + service_provider: Address, + ) -> anyhow::Result { let nonce = rand::rng().next_u64(); - let timestamp_ns = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() @@ -59,47 +106,115 @@ impl ReceiptSigner { .try_into() .map_err(|_| anyhow::anyhow!("failed to convert timestamp to ns"))?; - let receipt = TapReceipt { - allocation_id: allocation.0.0.into(), + let receipt = tap_graph::v2::Receipt { + collection_id: collection.0.into(), + payer, + data_service, + service_provider, timestamp_ns, nonce, value: fee, }; - let signed = SignedReceipt::new(&self.domain, receipt, &self.signer) - .map_err(|e| anyhow::anyhow!("failed to sign receipt: {:?}", e))?; + + // DEBUG: Log all receipt fields before signing + tracing::debug!( + collection_id = ?receipt.collection_id, + payer = ?receipt.payer, + data_service = ?receipt.data_service, + service_provider = ?receipt.service_provider, + timestamp_ns = receipt.timestamp_ns, + nonce = receipt.nonce, + value = receipt.value, + "TAP receipt fields before signing" + ); + + // DEBUG: Log EIP-712 domain components + tracing::debug!( + domain_name = ?self.v2_config.domain.name, + domain_version = ?self.v2_config.domain.version, + domain_chain_id = ?self.v2_config.domain.chain_id, + domain_verifying_contract = ?self.v2_config.domain.verifying_contract, + "TAP EIP-712 domain components" + ); + + let signed = + tap_graph::v2::SignedReceipt::new(&self.v2_config.domain, receipt, &self.signer) + .map_err(|e| anyhow::anyhow!("failed to sign v2 receipt: {:?}", e))?; + + // DEBUG: Log the signature being generated + tracing::debug!( + signature = ?signed.signature, + signature_bytes = ?signed.signature.as_bytes(), + expected_signer = ?self.signer.address(), + "TAP receipt signature generated" + ); Ok(Receipt(signed)) } + + pub fn payer_address(&self) -> Address { + self.signer.address() + } } #[cfg(test)] mod tests { use thegraph_core::{ - allocation_id, alloy::{primitives::address, signers::local::PrivateKeySigner}, + collection_id, }; use super::*; - #[test] - fn create_receipt() { - //* Given + fn create_test_signer() -> ReceiptSigner { let secret_key = PrivateKeySigner::from_slice(&[0xcd; 32]).expect("invalid secret key"); - let signer = ReceiptSigner::new( + ReceiptSigner::new( secret_key, 1.try_into().expect("invalid chain id"), address!("177b557b12f22bb17a9d73dcc994d978dd6f5f89"), - ); + ) + } - let allocation = allocation_id!("89b23fea4e46d40e8a4c6cca723e2a03fdd4bec2"); + #[test] + fn create_v2_receipt() { + let signer = create_test_signer(); + let collection = + collection_id!("89b23fea4e46d40e8a4c6cca723e2a03fdd4bec2a00000000000000000000000"); let fee = 1000; - //* When - let res = signer.create_receipt(allocation, fee); + let receipt = signer + .create_receipt( + collection, + fee, + address!("1111111111111111111111111111111111111111"), // payer + address!("2222222222222222222222222222222222222222"), // data_service + address!("3333333333333333333333333333333333333333"), // service_provider + ) + .expect("failed to create v2 receipt"); - //* Then - let receipt = res.expect("failed to create tap receipt"); + assert_eq!(receipt.value(), fee); + assert_eq!(receipt.collection(), collection); + } + + #[test] + fn test_receipt_serialization() { + let signer = create_test_signer(); + let collection = + collection_id!("89b23fea4e46d40e8a4c6cca723e2a03fdd4bec2a00000000000000000000000"); + let fee = 1000; + let receipt = signer + .create_receipt( + collection, + fee, + address!("1111111111111111111111111111111111111111"), + address!("2222222222222222222222222222222222222222"), + address!("3333333333333333333333333333333333333333"), + ) + .expect("failed to create v2 receipt"); + + let serialized = receipt.serialize(); + assert!(!serialized.is_empty()); assert_eq!(receipt.value(), fee); } } diff --git a/src/reports.rs b/src/reports.rs index e65620e6..c0bcf230 100644 --- a/src/reports.rs +++ b/src/reports.rs @@ -25,6 +25,8 @@ pub struct IndexerRequest { pub indexer: IndexerId, pub deployment: DeploymentId, pub url: String, + /// Receipt contains either v1 (allocation-based) or v2 (collection-based) receipt. + /// For reporting, collection IDs are converted to addresses for backward compatibility. pub receipt: Receipt, pub subgraph_chain: String, pub result: Result, @@ -108,32 +110,41 @@ impl Reporter { let indexer_queries = client_request .indexer_requests .iter() - .map(|indexer_request| IndexerQueryProtobuf { - indexer: indexer_request.indexer.to_vec(), - deployment: indexer_request.deployment.to_vec(), - allocation: indexer_request.receipt.allocation().to_vec(), - indexed_chain: indexer_request.subgraph_chain.clone(), - url: indexer_request.url.clone(), - fee_grt: indexer_request.receipt.value() as f64 * 1e-18, - response_time_ms: indexer_request.response_time_ms as u32, - seconds_behind: indexer_request.seconds_behind, - result: indexer_request - .result - .as_ref() - .map(|_| "success".to_string()) - .unwrap_or_else(|err| err.to_string()), - indexer_errors: indexer_request - .result - .as_ref() - .map(|r| { - r.errors - .iter() - .map(|err| err.as_str()) - .collect::>() - .join("; ") - }) - .unwrap_or_default(), - blocks_behind: indexer_request.blocks_behind, + .map(|indexer_request| { + // Only v2 receipts exist in this system + let (allocation, collection) = ( + None, + Some(indexer_request.receipt.collection().as_ref().to_vec()), + ); + + IndexerQueryProtobuf { + indexer: indexer_request.indexer.to_vec(), + deployment: indexer_request.deployment.to_vec(), + allocation, + collection, + indexed_chain: indexer_request.subgraph_chain.clone(), + url: indexer_request.url.clone(), + fee_grt: indexer_request.receipt.value() as f64 * 1e-18, + response_time_ms: indexer_request.response_time_ms as u32, + seconds_behind: indexer_request.seconds_behind, + result: indexer_request + .result + .as_ref() + .map(|_| "success".to_string()) + .unwrap_or_else(|err| err.to_string()), + indexer_errors: indexer_request + .result + .as_ref() + .map(|r| { + r.errors + .iter() + .map(|err| err.as_str()) + .collect::>() + .join("; ") + }) + .unwrap_or_default(), + blocks_behind: indexer_request.blocks_behind, + } }) .collect(); @@ -186,10 +197,13 @@ impl Reporter { .and_then(|r| Some((r.original_response, r.attestation?))) { const MAX_PAYLOAD_BYTES: usize = 100_000; + // Only v2 receipts exist - use collection as address + let allocation = indexer_request.receipt.collection().as_address().to_vec(); + AttestationProtobuf { request: Some(indexer_request.request).filter(|r| r.len() <= MAX_PAYLOAD_BYTES), response: Some(original_response).filter(|r| r.len() <= MAX_PAYLOAD_BYTES), - allocation: indexer_request.receipt.allocation().0.0.into(), + allocation, subgraph_deployment: attestation.deployment.0.into(), request_cid: attestation.request_cid.0.into(), response_cid: attestation.response_cid.0.into(), @@ -256,9 +270,12 @@ pub struct IndexerQueryProtobuf { /// 32 bytes #[prost(bytes, tag = "2")] deployment: Vec, - /// 20 bytes - #[prost(bytes, tag = "3")] - allocation: Vec, + /// 20 bytes - Allocation ID for v1 receipts + #[prost(bytes, optional, tag = "3")] + allocation: Option>, + /// 32 bytes - Collection ID for v2 receipts + #[prost(bytes, optional, tag = "12")] + collection: Option>, #[prost(string, tag = "4")] indexed_chain: String, #[prost(string, tag = "5")] @@ -283,7 +300,7 @@ pub struct AttestationProtobuf { request: Option, #[prost(string, optional, tag = "2")] response: Option, - /// 20 bytes + /// 20 bytes - Collection ID converted to address for backward compatibility #[prost(bytes, tag = "3")] allocation: Vec, /// 32 bytes @@ -299,3 +316,93 @@ pub struct AttestationProtobuf { #[prost(bytes, tag = "7")] signature: Vec, } + +#[cfg(test)] +mod tests { + use thegraph_core::{ + alloy::{primitives::address, signers::local::PrivateKeySigner}, + collection_id, + }; + + use crate::receipts::ReceiptSigner; + + fn create_test_signer() -> ReceiptSigner { + let secret_key = PrivateKeySigner::from_slice(&[0xcd; 32]).expect("invalid secret key"); + ReceiptSigner::new( + secret_key, + 1.try_into().expect("invalid chain id"), + address!("177b557b12f22bb17a9d73dcc994d978dd6f5f89"), + ) + } + + #[test] + fn test_protobuf_fields_v2_receipt() { + let signer = create_test_signer(); + let collection = + collection_id!("89b23fea4e46d40e8a4c6cca723e2a03fdd4bec2a00000000000000000000000"); + let fee = 1000; + + let v2_receipt = signer + .create_receipt( + collection, + fee, + address!("1111111111111111111111111111111111111111"), + address!("2222222222222222222222222222222222222222"), + address!("3333333333333333333333333333333333333333"), + ) + .expect("failed to create v2 receipt"); + + // Test IndexerQueryProtobuf fields - only v2 receipts exist + let (allocation_field, collection_field): (Option>, Option>) = + (None, Some(v2_receipt.collection().as_ref().to_vec())); + + assert!( + allocation_field.is_none(), + "v2 receipt should not have allocation field" + ); + assert!( + collection_field.is_some(), + "v2 receipt should have collection field" + ); + assert_eq!(collection_field.unwrap(), collection.as_ref().to_vec()); + } + + /// Test that simulates tap-aggregator v2 receipt processing + #[test] + fn test_tap_aggregator_v2_compatibility() { + let signer = create_test_signer(); + let collection = + collection_id!("89b23fea4e46d40e8a4c6cca723e2a03fdd4bec2a00000000000000000000000"); + let fee = 1000u128; + + let v2_receipt = signer + .create_receipt( + collection, + fee, + address!("1111111111111111111111111111111111111111"), + address!("2222222222222222222222222222222222222222"), + address!("3333333333333333333333333333333333333333"), + ) + .expect("failed to create v2 receipt"); + + // Simulate IndexerQueryProtobuf creation (what gateway sends) - only v2 receipts + let (allocation_field, collection_field): (Option>, Option>) = + (None, Some(v2_receipt.collection().as_ref().to_vec())); + + // Verify format matches tap-aggregator v2 expectations + assert!( + allocation_field.is_none(), + "v2 receipt must not have allocation field" + ); + assert!( + collection_field.is_some(), + "v2 receipt must have collection field" + ); + + let collection_bytes = collection_field.unwrap(); + assert_eq!(collection_bytes.len(), 32, "collection should be 32 bytes"); + assert_eq!(collection_bytes, collection.as_ref().to_vec()); + + // v2 receipt verified by successful creation and collection extraction + } +}