From f9f4728ee2b8d77e9ae3b5a29461cc7f01607494 Mon Sep 17 00:00:00 2001 From: Jannis Pohlmann Date: Tue, 14 Nov 2023 13:56:43 +0100 Subject: [PATCH] WIP: rewrite subgraph service using new framework --- Cargo.lock | 1315 ++++++++--------- common/Cargo.toml | 6 +- common/src/allocations/monitor.rs | 75 +- common/src/attestations/dispute_manager.rs | 39 +- common/src/escrow_accounts.rs | 71 +- .../indexer_service/http/indexer_service.rs | 10 +- common/src/lib.rs | 2 +- common/src/subgraph_client/client.rs | 132 +- common/src/subgraph_client/mod.rs | 2 +- common/src/subgraph_client/monitor.rs | 41 +- service/Cargo.toml | 22 +- service/src/cli.rs | 9 + service/src/common/address.rs | 30 - service/src/common/database.rs | 34 - service/src/common/mod.rs | 6 - service/src/config.rs | 441 +++--- .../indexer_management/mod.rs => database.rs} | 15 +- service/src/graph_node.rs | 176 --- service/src/main.rs | 348 +++-- service/src/metrics/mod.rs | 79 - service/src/query_processor.rs | 257 ---- service/src/{server => }/routes/cost.rs | 47 +- service/src/routes/mod.rs | 4 + service/src/routes/status.rs | 114 ++ service/src/server/mod.rs | 134 -- service/src/server/routes/basic.rs | 43 - service/src/server/routes/deployment.rs | 148 -- service/src/server/routes/mod.rs | 66 - service/src/server/routes/network.rs | 49 - service/src/server/routes/status.rs | 90 -- service/src/server/routes/subgraphs.rs | 150 -- service/src/test_vectors.rs | 12 - service/src/util.rs | 61 - 33 files changed, 1359 insertions(+), 2669 deletions(-) create mode 100644 service/src/cli.rs delete mode 100644 service/src/common/address.rs delete mode 100644 service/src/common/database.rs delete mode 100644 service/src/common/mod.rs rename service/src/{common/indexer_management/mod.rs => database.rs} (97%) delete mode 100644 service/src/graph_node.rs delete mode 100644 service/src/metrics/mod.rs delete mode 100644 service/src/query_processor.rs rename service/src/{server => }/routes/cost.rs (64%) create mode 100644 service/src/routes/mod.rs create mode 100644 service/src/routes/status.rs delete mode 100644 service/src/server/mod.rs delete mode 100644 service/src/server/routes/basic.rs delete mode 100644 service/src/server/routes/deployment.rs delete mode 100644 service/src/server/routes/mod.rs delete mode 100644 service/src/server/routes/network.rs delete mode 100644 service/src/server/routes/status.rs delete mode 100644 service/src/server/routes/subgraphs.rs delete mode 100644 service/src/test_vectors.rs delete mode 100644 service/src/util.rs diff --git a/Cargo.lock b/Cargo.lock index 9ef7449ed..64d13d040 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,25 +40,26 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", - "getrandom 0.2.10", + "getrandom 0.2.11", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -119,7 +120,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "syn-solidity", "tiny-keccak", ] @@ -385,45 +386,13 @@ dependencies = [ [[package]] name = "async-graphql" -version = "4.0.16" +version = "6.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ed522678d412d77effe47b3c82314ac36952a35e6e852093dd48287c421f80" +checksum = "298a5d587d6e6fdb271bf56af2dc325a80eb291fd0fc979146584b9a05494a8c" dependencies = [ - "async-graphql-derive 4.0.16", - "async-graphql-parser 4.0.16", - "async-graphql-value 4.0.16", - "async-stream", - "async-trait", - "base64 0.13.1", - "bytes", - "fast_chemail", - "fnv", - "futures-util", - "http", - "indexmap 1.9.3", - "mime", - "multer", - "num-traits", - "once_cell", - "pin-project-lite", - "regex", - "serde", - "serde_json", - "serde_urlencoded", - "static_assertions", - "tempfile", - "thiserror", -] - -[[package]] -name = "async-graphql" -version = "6.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1addb0b551c59640e15de99e7566a4e3a1186cf42269e160c485ba6d8b43fe30" -dependencies = [ - "async-graphql-derive 6.0.7", - "async-graphql-parser 6.0.7", - "async-graphql-value 6.0.7", + "async-graphql-derive", + "async-graphql-parser", + "async-graphql-value", "async-stream", "async-trait", "base64 0.13.1", @@ -433,7 +402,7 @@ dependencies = [ "futures-util", "handlebars", "http", - "indexmap 2.0.2", + "indexmap 2.1.0", "mime", "multer", "num-traits", @@ -450,73 +419,46 @@ dependencies = [ [[package]] name = "async-graphql-axum" -version = "4.0.16" +version = "6.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91ac174c05670edffb720bc376b9d4c274c3d127ac08ed3d38144c9415502cd" +checksum = "01a1c20a2059bffbc95130715b23435a05168c518fba9709c81fa2a38eed990c" dependencies = [ - "async-graphql 4.0.16", + "async-graphql", "async-trait", - "axum 0.5.17", + "axum", "bytes", "futures-util", - "http-body", "serde_json", + "tokio", + "tokio-stream", "tokio-util", "tower-service", ] [[package]] name = "async-graphql-derive" -version = "4.0.16" +version = "6.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c121a894495d7d3fc3d4e15e0a9843e422e4d1d9e3c514d8062a1c94b35b005d" +checksum = "c7f329c7eb9b646a72f70c9c4b516c70867d356ec46cb00dcac8ad343fd006b0" dependencies = [ "Inflector", - "async-graphql-parser 4.0.16", - "darling 0.14.4", - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "async-graphql-derive" -version = "6.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1121ff0be2feea705c24f6940162c4f14a077e50a217b16e091e6534a8c08a" -dependencies = [ - "Inflector", - "async-graphql-parser 6.0.7", - "darling 0.20.3", + "async-graphql-parser", + "darling", "proc-macro-crate 1.3.1", "proc-macro2", "quote", "strum 0.25.0", - "syn 2.0.38", + "syn 2.0.39", "thiserror", ] [[package]] name = "async-graphql-parser" -version = "4.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6c386f398145c6180206c1869c2279f5a3d45db5be4e0266148c6ac5c6ad68" -dependencies = [ - "async-graphql-value 4.0.16", - "pest", - "serde", - "serde_json", -] - -[[package]] -name = "async-graphql-parser" -version = "6.0.7" +version = "6.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b6713fd4ffd610b8b6f6e911bf31277cbb84b7c2a9cdeeb39d1b3eed3b88e4" +checksum = "6139181845757fd6a73fbb8839f3d036d7150b798db0e9bb3c6e83cdd65bd53b" dependencies = [ - "async-graphql-value 6.0.7", + "async-graphql-value", "pest", "serde", "serde_json", @@ -524,24 +466,12 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "4.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a941b499fead4a3fb5392cabf42446566d18c86313f69f2deab69560394d65f" -dependencies = [ - "bytes", - "indexmap 1.9.3", - "serde", - "serde_json", -] - -[[package]] -name = "async-graphql-value" -version = "6.0.7" +version = "6.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d74240f9daa8c1e8f73e9cfcc338d20a88d00bbeb83ded49ce8e5b4dcec0f5" +checksum = "323a5143f5bdd2030f45e3f2e0c821c9b1d36e79cf382129c64299c50a7f3750" dependencies = [ "bytes", - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_json", ] @@ -565,7 +495,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -576,7 +506,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -599,6 +529,25 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-write-file" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c232177ba50b16fe7a4588495bd474a62a9e45a8e4ca6fd7d0b7ac29d164631e" +dependencies = [ + "nix", + "rand 0.8.5", +] + [[package]] name = "atty" version = "0.2.14" @@ -688,41 +637,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "axum" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" -dependencies = [ - "async-trait", - "axum-core 0.2.9", - "base64 0.13.1", - "bitflags 1.3.2", - "bytes", - "futures-util", - "headers", - "http", - "http-body", - "hyper", - "itoa", - "matchit 0.5.0", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sha-1 0.10.1", - "sync_wrapper", - "tokio", - "tokio-tungstenite 0.17.2", - "tower", - "tower-http 0.3.5", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.6.20" @@ -730,7 +644,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core 0.3.4", + "axum-core", + "base64 0.21.5", "bitflags 1.3.2", "bytes", "futures-util", @@ -739,7 +654,7 @@ dependencies = [ "http-body", "hyper", "itoa", - "matchit 0.7.3", + "matchit", "memchr", "mime", "percent-encoding", @@ -749,29 +664,15 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", + "sha1", "sync_wrapper", "tokio", + "tokio-tungstenite", "tower", "tower-layer", "tower-service", ] -[[package]] -name = "axum-core" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.3.4" @@ -818,9 +719,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -939,47 +840,26 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "bf617fabf5cdbdc92f774bfe5062d870f228b80056d41180797abf48bed4056e" dependencies = [ "borsh-derive", - "hashbrown 0.13.1", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "f404657a7ea7b5249e36808dff544bc88a28f26e0ac40009f674b7a009d14be3" dependencies = [ + "once_cell", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", + "syn_derive", ] [[package]] @@ -994,9 +874,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -1019,10 +899,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b69d6331ec579144d39e1c128f343d23e9b837617df1bed4ed032e141f83f06a" dependencies = [ "anyhow", - "base64 0.21.4", + "base64 0.21.5", "bincode", "build-info-common", - "cargo_metadata 0.18.1", + "cargo_metadata", "chrono", "git2", "glob", @@ -1051,7 +931,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fc1874cb1995691fb01f9bb56e75f9660d2614e74607fa71c08a8b3bd7e30e4" dependencies = [ "anyhow", - "base64 0.21.4", + "base64 0.21.5", "bincode", "build-info-common", "chrono", @@ -1061,7 +941,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.38", + "syn 2.0.39", "zstd 0.12.4", ] @@ -1105,6 +985,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + [[package]] name = "byteorder" version = "1.5.0" @@ -1158,25 +1044,11 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" [[package]] name = "cargo-platform" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.17.0" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.20", "serde", - "serde_json", - "thiserror", ] [[package]] @@ -1240,9 +1112,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -1250,9 +1122,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -1262,21 +1134,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "coins-bip32" @@ -1316,7 +1188,7 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bech32", "bs58", "digest 0.10.7", @@ -1372,13 +1244,14 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37be52ef5e3b394db27a2341010685ad5103c72ac15ce2e9420a7e8f93f342c" +checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557" dependencies = [ "cfg-if", "cpufeatures", "hex", + "proptest", "serde", ] @@ -1438,9 +1311,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1456,9 +1329,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" @@ -1499,7 +1372,7 @@ dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", + "memoffset 0.9.0", "scopeguard", ] @@ -1530,9 +1403,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1559,38 +1432,14 @@ dependencies = [ "cipher", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1604,18 +1453,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.38", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -1624,9 +1462,9 @@ version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.20.3", + "darling_core", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1644,9 +1482,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "deadpool" @@ -1821,9 +1659,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -1844,9 +1682,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -1885,7 +1723,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "hex", "k256", @@ -1918,9 +1756,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys", @@ -2009,9 +1847,9 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad13497f6e0a24292fc7b408e30d22fe9dc262da1f40d7b542c3a44e7fc0476" +checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -2025,9 +1863,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e9e8acd0ed348403cc73a670c24daba3226c40b98dc1a41903766b3ab6240a" +checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" dependencies = [ "ethers-core", "once_cell", @@ -2037,9 +1875,9 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d79269278125006bb0552349c03593ffa9702112ca88bc7046cc669f148fb47c" +checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -2056,9 +1894,9 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95a43c939b2e4e2f3191c5ad4a1f279780b8a39139c9905b43a7433531e2ab" +checksum = "51258120c6b47ea9d9bec0d90f9e8af71c977fbefbef8213c91bfed385fe45eb" dependencies = [ "Inflector", "const-hex", @@ -2073,16 +1911,16 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.38", - "toml 0.7.8", + "syn 2.0.39", + "toml 0.8.8", "walkdir", ] [[package]] name = "ethers-contract-derive" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9ce44906fc871b3ee8c69a695ca7ec7f70e50cb379c9b9cb5e532269e492f6" +checksum = "936e7a0f1197cee2b62dc89f63eff3201dbf87c283ff7e18d86d38f83b845483" dependencies = [ "Inflector", "const-hex", @@ -2091,18 +1929,18 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "ethers-core" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0a17f0708692024db9956b31d7a20163607d2745953f5ae8125ab368ba280ad" +checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" dependencies = [ "arrayvec", "bytes", - "cargo_metadata 0.17.0", + "cargo_metadata", "chrono", "const-hex", "elliptic-curve", @@ -2117,7 +1955,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.38", + "syn 2.0.39", "tempfile", "thiserror", "tiny-keccak", @@ -2126,10 +1964,11 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e53451ea4a8128fbce33966da71132cf9e1040dcfd2a2084fd7733ada7b2045" +checksum = "abbac2c890bdbe0f1b8e549a53b00e2c4c1de86bb077c1094d1f38cdf9381a56" dependencies = [ + "chrono", "ethers-core", "reqwest", "semver 1.0.20", @@ -2141,9 +1980,9 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473f1ccd0c793871bbc248729fa8df7e6d2981d6226e4343e3bbaa9281074d5d" +checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" dependencies = [ "async-trait", "auto_impl", @@ -2168,13 +2007,13 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6838fa110e57d572336178b7c79e94ff88ef976306852d8cb87d9e5b1fc7c0b5" +checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.4", + "base64 0.21.5", "bytes", "const-hex", "enr", @@ -2193,7 +2032,7 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "tracing", "tracing-futures", "url", @@ -2205,9 +2044,9 @@ dependencies = [ [[package]] name = "ethers-signers" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea44bec930f12292866166f9ddbea6aa76304850e4d8dcd66dc492b43d00ff1" +checksum = "0cb1b714e227bbd2d8c53528adb580b203009728b17d0d0e4119353aa9bc5532" dependencies = [ "async-trait", "coins-bip32", @@ -2224,9 +2063,9 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de34e484e7ae3cab99fbfd013d6c5dc7f9013676a4e0e414d8b12e1213e8b3ba" +checksum = "a64f710586d147864cff66540a6d64518b9ff37d73ef827fee430538265b595f" dependencies = [ "cfg-if", "const-hex", @@ -2251,7 +2090,7 @@ dependencies = [ "tokio", "tracing", "walkdir", - "yansi", + "yansi 0.5.1", ] [[package]] @@ -2274,9 +2113,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" dependencies = [ "indenter", "once_cell", @@ -2333,11 +2172,11 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15473d7f83b54a44826907af16ae5727eaacaf6e53b51474016d3efd9aa35d5" dependencies = [ - "darling 0.20.3", + "darling", "proc-macro2", "quote", - "syn 2.0.38", - "uuid 1.5.0", + "syn 2.0.39", + "uuid 1.6.1", ] [[package]] @@ -2350,6 +2189,20 @@ dependencies = [ "subtle", ] +[[package]] +name = "figment" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649f3e5d826594057e9a519626304d8da859ea8a0b18ce99500c586b8d45faee" +dependencies = [ + "atomic", + "pear", + "serde", + "toml 0.8.8", + "uncased", + "version_check", +] + [[package]] name = "finl_unicode" version = "1.2.0" @@ -2424,9 +2277,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -2459,9 +2312,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -2474,9 +2327,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -2484,15 +2337,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -2512,9 +2365,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -2543,26 +2396,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -2576,9 +2429,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -2625,9 +2478,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -2636,9 +2489,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" @@ -2704,14 +2557,27 @@ dependencies = [ [[package]] name = "graphql" -version = "0.1.0" -source = "git+https://github.com/edgeandnode/toolshed?branch=main#e9f344633ef0d78a3209fac295de57c6397bd009" +version = "0.2.0" +source = "git+https://github.com/edgeandnode/toolshed?branch=main#920005386bbf3bae6e908f6887b19c1fa55c2802" dependencies = [ "firestorm", "graphql-parser", "serde", ] +[[package]] +name = "graphql-http" +version = "0.1.1" +source = "git+https://github.com/edgeandnode/toolshed?branch=main#920005386bbf3bae6e908f6887b19c1fa55c2802" +dependencies = [ + "anyhow", + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "graphql-parser" version = "0.4.0" @@ -2735,9 +2601,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -2745,7 +2611,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -2754,9 +2620,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683" +checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" dependencies = [ "log", "pest", @@ -2772,7 +2638,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -2781,7 +2647,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", ] [[package]] @@ -2790,7 +2656,7 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", "allocator-api2", ] @@ -2818,7 +2684,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "headers-core", "http", @@ -2915,9 +2781,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2997,7 +2863,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -3006,9 +2872,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -3064,9 +2930,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -3126,14 +2992,14 @@ dependencies = [ "arc-swap", "async-trait", "autometrics 0.6.0", - "axum 0.6.20", + "axum", "build-info", "env_logger", "ethers", "ethers-core", "eventuals", "faux", - "graphql", + "graphql-http", "headers", "headers-derive", "keccak-hash", @@ -3174,7 +3040,7 @@ dependencies = [ "ethers-signers", "eventuals", "indexer-common", - "jsonrpsee 0.20.2", + "jsonrpsee 0.20.3", "lazy_static", "reqwest", "serde", @@ -3205,9 +3071,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.2", @@ -3220,6 +3086,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + [[package]] name = "inout" version = "0.1.3" @@ -3240,9 +3112,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -3290,9 +3162,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -3312,14 +3184,14 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de902baa44bf34a58b1a4906f8b840d7d60dcec5f41fe08b4dbc14cf9efa821c" +checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ - "jsonrpsee-core 0.20.2", + "jsonrpsee-core 0.20.3", "jsonrpsee-http-client", - "jsonrpsee-proc-macros 0.20.2", - "jsonrpsee-types 0.20.2", + "jsonrpsee-proc-macros 0.20.3", + "jsonrpsee-types 0.20.3", "tracing", ] @@ -3349,16 +3221,16 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f45d37af23707750136379f6799e76ebfcf2d425ec4e36d0deb7921da5e65c" +checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" dependencies = [ "anyhow", "async-trait", "beef", "futures-util", "hyper", - "jsonrpsee-types 0.20.2", + "jsonrpsee-types 0.20.3", "serde", "serde_json", "thiserror", @@ -3368,15 +3240,15 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02308562f2e8162a32f8d6c3dc19c29c858d5d478047c886a5c3c25b5f7fa868" +checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" dependencies = [ "async-trait", "hyper", "hyper-rustls", - "jsonrpsee-core 0.20.2", - "jsonrpsee-types 0.20.2", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", "serde", "serde_json", "thiserror", @@ -3401,9 +3273,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26b3675a943d083d0bf6e367ec755dccec56c41888afa13b191c1c4ff87c652" +checksum = "29110019693a4fa2dbda04876499d098fa16d70eba06b1e6e2b3f1b251419515" dependencies = [ "heck", "proc-macro-crate 1.3.1", @@ -3448,9 +3320,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05eaff23af19f10ba6fbb76519bed6da4d3b9bbaef13d39b7c2b6c14e532d27e" +checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" dependencies = [ "anyhow", "beef", @@ -3466,9 +3338,9 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -3476,9 +3348,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" dependencies = [ "cfg-if", "ecdsa", @@ -3546,9 +3418,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libgit2-sys" @@ -3568,11 +3440,22 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + [[package]] name = "libsqlite3-sys" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" dependencies = [ "cc", "pkg-config", @@ -3608,14 +3491,14 @@ checksum = "ba125974b109d512fccbc6c0244e7580143e460895dfd6ea7f8bbb692fd94396" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -3669,12 +3552,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matchit" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" - [[package]] name = "matchit" version = "0.7.3" @@ -3697,6 +3574,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -3712,7 +3598,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", "metrics-macros 0.6.0", "portable-atomic 0.3.20", ] @@ -3723,9 +3609,9 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", "metrics-macros 0.7.0", - "portable-atomic 1.4.3", + "portable-atomic 1.5.1", ] [[package]] @@ -3749,7 +3635,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "indexmap 1.9.3", "metrics 0.21.1", "metrics-util 0.15.1", @@ -3776,7 +3662,7 @@ checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3834,9 +3720,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -3891,6 +3777,19 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", +] + [[package]] name = "no-std-compat" version = "0.4.1" @@ -4000,23 +3899,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4067,9 +3966,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -4088,7 +3987,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4099,9 +3998,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", @@ -4283,7 +4182,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets", ] @@ -4333,6 +4232,29 @@ dependencies = [ "hmac", ] +[[package]] +name = "pear" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi 1.0.0-rc.1", +] + +[[package]] +name = "pear_codegen" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.39", +] + [[package]] name = "pem" version = "1.1.1" @@ -4353,15 +4275,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", "thiserror", @@ -4370,9 +4292,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" dependencies = [ "pest", "pest_generator", @@ -4380,22 +4302,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" dependencies = [ "once_cell", "pest", @@ -4409,7 +4331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.2", + "indexmap 2.1.0", ] [[package]] @@ -4452,7 +4374,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4490,7 +4412,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4538,14 +4460,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" dependencies = [ - "portable-atomic 1.4.3", + "portable-atomic 1.5.1", ] [[package]] name = "portable-atomic" -version = "1.4.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" [[package]] name = "powerfmt" @@ -4572,7 +4494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ "diff", - "yansi", + "yansi 0.5.1", ] [[package]] @@ -4582,7 +4504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4601,21 +4523,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "toml 0.5.11", + "once_cell", + "toml_edit 0.19.15", ] [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit", + "toml_edit 0.20.7", ] [[package]] @@ -4651,6 +4573,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "version_check", + "yansi 1.0.0-rc.1", +] + [[package]] name = "prometheus" version = "0.13.3" @@ -4686,14 +4621,14 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "proptest" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", @@ -4703,7 +4638,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", @@ -4847,7 +4782,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -4897,24 +4832,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -4926,12 +4843,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -5000,7 +4917,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -5063,11 +4980,25 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +dependencies = [ + "cc", + "getrandom 0.2.11", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -5091,7 +5022,7 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.5.0", + "uuid 1.6.1", ] [[package]] @@ -5129,16 +5060,14 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "6a3211b01eea83d80687da9eef70e39d65144a3894866a5153a2723e425a157f" dependencies = [ - "byteorder", "const-oid", "digest 0.10.7", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -5177,9 +5106,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95294d6e3a6192f3aabf91c38f56505a625aa495533442744185a36d75a790c4" +checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -5187,6 +5116,7 @@ dependencies = [ "bytes", "fastrlp", "num-bigint", + "num-traits", "parity-scale-codec", "primitive-types", "proptest", @@ -5206,9 +5136,9 @@ checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" [[package]] name = "rust_decimal" -version = "1.32.0" +version = "1.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4" dependencies = [ "arrayvec", "borsh", @@ -5258,9 +5188,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -5271,12 +5201,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", - "ring", + "ring 0.17.5", "rustls-webpki", "sct", ] @@ -5295,21 +5225,21 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", ] [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -5356,9 +5286,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" dependencies = [ "cfg-if", "derive_more", @@ -5368,9 +5298,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", @@ -5407,12 +5337,12 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -5517,29 +5447,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -5569,9 +5499,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -5594,11 +5524,11 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -5611,19 +5541,19 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ - "darling 0.20.3", + "darling", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -5637,10 +5567,10 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "anyhow", - "async-graphql 4.0.16", + "async-graphql", "async-graphql-axum", "autometrics 0.3.3", - "axum 0.5.17", + "axum", "build-info", "build-info-build", "cargo-husky", @@ -5652,6 +5582,9 @@ dependencies = [ "ethers-core", "eventuals", "faux", + "figment", + "graphql", + "graphql-http", "hex", "hex-literal", "hyper", @@ -5663,16 +5596,16 @@ dependencies = [ "reqwest", "serde", "serde_json", + "serde_spanned", "sha3", "sqlx", "tap_core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "test-log", "thiserror", "tokio", - "toml 0.7.8", "toolshed", "tower", - "tower-http 0.4.4", + "tower-http", "tracing", "tracing-subscriber", "wiremock", @@ -5691,17 +5624,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha1" version = "0.10.6" @@ -5754,9 +5676,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -5803,9 +5725,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smol_str" @@ -5818,9 +5740,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -5828,9 +5750,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys", @@ -5849,14 +5771,14 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "sha-1 0.9.8", + "sha-1", ] [[package]] name = "solang-parser" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb9fa2fa2fa6837be8a2495486ff92e3ffe68a99b6eeba288e139efdd842457" +checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" dependencies = [ "itertools 0.11.0", "lalrpop", @@ -5874,7 +5796,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -5915,9 +5837,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33" +checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" dependencies = [ "sqlx-core", "sqlx-macros", @@ -5928,11 +5850,11 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" +checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", "atoi", "bigdecimal 0.3.1", "byteorder", @@ -5949,7 +5871,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.0.2", + "indexmap 2.1.0", "log", "memchr", "once_cell", @@ -5971,9 +5893,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec" +checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" dependencies = [ "proc-macro2", "quote", @@ -5984,10 +5906,11 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc" +checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" dependencies = [ + "atomic-write-file", "dotenvy", "either", "heck", @@ -6010,12 +5933,12 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" +checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ "atoi", - "base64 0.21.4", + "base64 0.21.5", "bigdecimal 0.3.1", "bitflags 2.4.1", "byteorder", @@ -6055,12 +5978,12 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" +checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ "atoi", - "base64 0.21.4", + "base64 0.21.5", "bigdecimal 0.3.1", "bitflags 2.4.1", "byteorder", @@ -6098,9 +6021,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f" +checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" dependencies = [ "atoi", "flume", @@ -6117,6 +6040,7 @@ dependencies = [ "time", "tracing", "url", + "urlencoding", ] [[package]] @@ -6196,7 +6120,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6207,9 +6131,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "svm-rs" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597e3a746727984cb7ea2487b6a40726cad0dbe86628e7d429aa6b8c4c153db4" +checksum = "20689c7d03b6461b502d0b95d6c24874c7d24dea2688af80486a130a06af3b07" dependencies = [ "dirs", "fs2", @@ -6238,9 +6162,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -6256,7 +6180,19 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", +] + +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.39", ] [[package]] @@ -6301,7 +6237,7 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "anyhow", - "axum 0.6.20", + "axum", "clap", "ethereum-types", "ethers-core", @@ -6371,13 +6307,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", "windows-sys", ] @@ -6395,9 +6331,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -6410,7 +6346,7 @@ checksum = "f66edd6b6cd810743c0c71e1d085e92b01ce6a72782032e3f794c8284fe4bcdd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6430,7 +6366,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6498,9 +6434,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -6510,20 +6446,20 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6557,18 +6493,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.17.3", -] - [[package]] name = "tokio-tungstenite" version = "0.20.1" @@ -6580,15 +6504,15 @@ dependencies = [ "rustls", "tokio", "tokio-rustls", - "tungstenite 0.20.1", + "tungstenite", "webpki-roots", ] [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -6610,21 +6534,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -6635,7 +6559,29 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -6644,12 +6590,12 @@ dependencies = [ [[package]] name = "toolshed" -version = "0.2.2" -source = "git+https://github.com/edgeandnode/toolshed?branch=main#e9f344633ef0d78a3209fac295de57c6397bd009" +version = "0.2.3" +source = "git+https://github.com/edgeandnode/toolshed?branch=main#920005386bbf3bae6e908f6887b19c1fa55c2802" dependencies = [ "alloy-primitives", "alloy-sol-types", - "async-graphql 6.0.7", + "async-graphql", "bs58", "ethers-core", "firestorm", @@ -6678,25 +6624,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" -dependencies = [ - "bitflags 1.3.2", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "tower-http" version = "0.4.4" @@ -6734,7 +6661,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db81d9313372d714152194f3f2b66badda23a783fb6a97462e35f632814f4cff" dependencies = [ - "axum 0.6.20", + "axum", "forwarded-header-value", "futures", "futures-core", @@ -6768,7 +6695,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6793,12 +6720,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -6814,9 +6741,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -6839,25 +6766,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand 0.8.5", - "sha-1 0.10.1", - "thiserror", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.20.1" @@ -6908,6 +6816,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "uncased" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -6968,11 +6885,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -7004,17 +6927,17 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "serde", ] [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -7095,9 +7018,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -7105,24 +7028,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -7132,9 +7055,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7142,28 +7065,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -7171,9 +7094,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "whoami" @@ -7289,9 +7212,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -7308,13 +7231,13 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.19" +version = "0.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" +checksum = "079aee011e8a8e625d16df9e785de30a6b77f80a6126092d76a57375f96448da" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "deadpool", "futures", "futures-timer", @@ -7362,11 +7285,37 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yansi" +version = "1.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -7379,7 +7328,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] diff --git a/common/Cargo.toml b/common/Cargo.toml index 08da26c77..c78a87e69 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -30,10 +30,10 @@ sqlx = { version = "0.7.1", features = [ "time", ] } tokio = { version = "1.32.0", features = ["full", "macros", "rt"] } -toolshed = { git = "https://github.com/edgeandnode/toolshed", branch = "main", features = [ - "graphql", +toolshed = { git = "https://github.com/edgeandnode/toolshed", branch = "main" } +graphql-http = { git = "https://github.com/edgeandnode/toolshed", branch = "main", features = [ + "http-reqwest", ] } -graphql = { git = "https://github.com/edgeandnode/toolshed", branch = "main" } tap_core = "0.6.0" axum = { version = "0.6.20", default_features = true, features = ["headers"] } thiserror = "1.0.49" diff --git a/common/src/allocations/monitor.rs b/common/src/allocations/monitor.rs index eddb0b732..eb49f76e6 100644 --- a/common/src/allocations/monitor.rs +++ b/common/src/allocations/monitor.rs @@ -7,11 +7,10 @@ use alloy_primitives::Address; use anyhow::anyhow; use eventuals::{timer, Eventual, EventualExt}; use serde::Deserialize; -use serde_json::json; use tokio::time::sleep; use tracing::warn; -use crate::prelude::SubgraphClient; +use crate::prelude::{Query, SubgraphClient}; use super::Allocation; @@ -22,7 +21,7 @@ async fn current_epoch( // Types for deserializing the network subgraph response #[derive(Deserialize)] #[serde(rename_all = "camelCase")] - struct GraphNetworkResponse { + struct GraphNetworkData { graph_network: Option, } #[derive(Deserialize)] @@ -33,30 +32,15 @@ async fn current_epoch( // Query the current epoch let query = r#"query epoch($id: ID!) { graphNetwork(id: $id) { currentEpoch } }"#; - let response = network_subgraph - .query::(&json!({ - "query": query, - "variables": { - "id": graph_network_id - } - })) + let result = network_subgraph + .query::(Query::new_with_variables( + query, + [("id", graph_network_id.into())], + )) .await?; - if let Some(errors) = response.errors { - warn!( - "Errors encountered identifying current epoch for network {}: {}", - graph_network_id, - errors - .into_iter() - .map(|e| e.message) - .collect::>() - .join(", ") - ); - } - - response - .data - .and_then(|data| data.graph_network) + result? + .graph_network .ok_or_else(|| anyhow!("Network {} not found", graph_network_id)) .map(|network| network.current_epoch) } @@ -137,42 +121,35 @@ pub fn indexer_allocations( // Query active and recently closed allocations for the indexer, // using the network subgraph let response = network_subgraph - .query::(&json!({ - "query": query, - "variables": { - "indexer": format!("{indexer_address:?}"), - "closedAtEpochThreshold": closed_at_epoch_threshold, - }})) + .query::(Query::new_with_variables( + query, + [ + ("indexer", format!("{indexer_address:?}").into()), + ("closedAtEpochThreshold", closed_at_epoch_threshold.into()), + ], + )) .await .map_err(|e| e.to_string())?; - // If there are any GraphQL errors returned, we'll log them for debugging - if let Some(errors) = response.errors { - warn!( - "Errors encountered fetching active or recently closed allocations for indexer {:?}: {}", - indexer_address, - errors.into_iter().map(|e| e.message).collect::>().join(", ") - ); - } - - // Verify that the indexer could be found at all - let indexer = response - .data - .and_then(|data| data.indexer) - .ok_or_else(|| format!("Indexer {:?} could not be found on the network", indexer_address))?; + let indexer = response.map_err(|e| e.to_string()).and_then(|data| { + // Verify that the indexer could be found at all + data.indexer + .ok_or_else(|| format!("Indexer `{indexer_address}` not found on the network")) + })?; // Pull active and recently closed allocations out of the indexer let Indexer { active_allocations, - recently_closed_allocations + recently_closed_allocations, } = indexer; Ok(HashMap::from_iter( - active_allocations.into_iter().map(|a| (a.id, a)).chain( - recently_closed_allocations.into_iter().map(|a| (a.id, a))) + active_allocations + .into_iter() + .map(|a| (a.id, a)) + .chain(recently_closed_allocations.into_iter().map(|a| (a.id, a))), )) }, - // Need to use string errors here because eventuals `map_with_retry` retries // errors that can be cloned move |err: String| { diff --git a/common/src/attestations/dispute_manager.rs b/common/src/attestations/dispute_manager.rs index 0a19075ed..bbbf6dba8 100644 --- a/common/src/attestations/dispute_manager.rs +++ b/common/src/attestations/dispute_manager.rs @@ -6,11 +6,10 @@ use std::time::Duration; use alloy_primitives::Address; use eventuals::{timer, Eventual, EventualExt}; use serde::Deserialize; -use serde_json::json; use tokio::time::sleep; use tracing::warn; -use crate::subgraph_client::SubgraphClient; +use crate::subgraph_client::{Query, SubgraphClient}; pub fn dispute_manager( network_subgraph: &'static SubgraphClient, @@ -32,40 +31,26 @@ pub fn dispute_manager( timer(interval).map_with_retry( move |_| async move { let response = network_subgraph - .query::(&json!({ - "query": r#" + .query::(Query::new_with_variables( + r#" query network($id: ID!) { graphNetwork(id: $id) { disputeManager } } "#, - "variables": { - "id": graph_network_id - } - })) + [("id", graph_network_id.into())], + )) .await .map_err(|e| e.to_string())?; - if let Some(errors) = response.errors { - warn!( - "Errors encountered querying the dispute manager for network {}: {}", - graph_network_id, - errors - .into_iter() - .map(|e| e.message) - .collect::>() - .join(", ") - ); - } - - response - .data - .and_then(|data| data.graph_network) - .map(|network| network.dispute_manager) - .ok_or_else(|| { - format!("Network {} not found in network subgraph", graph_network_id) - }) + response.map_err(|e| e.to_string()).and_then(|data| { + data.graph_network + .map(|network| network.dispute_manager) + .ok_or_else(|| { + format!("Network {} not found in network subgraph", graph_network_id) + }) + }) }, move |err: String| { warn!( diff --git a/common/src/escrow_accounts.rs b/common/src/escrow_accounts.rs index 7ebdcc0f4..583aa05fa 100644 --- a/common/src/escrow_accounts.rs +++ b/common/src/escrow_accounts.rs @@ -8,11 +8,10 @@ use anyhow::Result; use ethers_core::types::U256; use eventuals::{timer, Eventual, EventualExt}; use serde::Deserialize; -use serde_json::json; use tokio::time::sleep; use tracing::{error, warn}; -use crate::prelude::SubgraphClient; +use crate::prelude::{Query, SubgraphClient}; pub fn escrow_accounts( escrow_subgraph: &'static SubgraphClient, @@ -44,8 +43,8 @@ pub fn escrow_accounts( timer(interval).map_with_retry( move |_| async move { let response = escrow_subgraph - .query::(&json!({ - "query": r#" + .query::(Query::new_with_variables( + r#" query ($indexer: ID!) { escrowAccounts(where: {receiver_: {id: $indexer}}) { balance @@ -56,51 +55,33 @@ pub fn escrow_accounts( } } "#, - "variables": { - "indexer": indexer_address, - } - } + [("indexer", indexer_address.to_string().into())], )) .await .map_err(|e| e.to_string())?; - // If there are any GraphQL errors returned, we'll log them for debugging - if let Some(errors) = response.errors { - error!( - "Errors encountered fetching escrow accounts for indexer {:?}: {}", - indexer_address, - errors - .into_iter() - .map(|e| e.message) - .collect::>() - .join(", ") - ); - } - - let sender_accounts = response - .data - .map_or(vec![], |data| data.escrow_accounts) - .iter() - .map(|account| { - let balance = U256::checked_sub( - U256::from_dec_str(&account.balance)?, - U256::from_dec_str(&account.total_amount_thawing)?, - ) - .unwrap_or_else(|| { - warn!( - "Balance minus total amount thawing underflowed for account {}. \ - Setting balance to 0, no queries will be served for this sender.", - account.sender.id - ); - U256::from(0) - }); - - Ok((account.sender.id, balance)) - }) - .collect::, anyhow::Error>>() - .map_err(|e| format!("{}", e))?; - - Ok(sender_accounts) + response.map_err(|e| e.to_string()).and_then(|data| { + data.escrow_accounts + .iter() + .map(|account| { + let balance = U256::checked_sub( + U256::from_dec_str(&account.balance)?, + U256::from_dec_str(&account.total_amount_thawing)?, + ) + .unwrap_or_else(|| { + warn!( + "Balance minus total amount thawing underflowed for account {}. \ + Setting balance to 0, no queries will be served for this sender.", + account.sender.id + ); + U256::from(0) + }); + + Ok((account.sender.id, balance)) + }) + .collect::, anyhow::Error>>() + .map_err(|e| format!("{}", e)) + }) }, move |err: String| { error!( diff --git a/common/src/indexer_service/http/indexer_service.rs b/common/src/indexer_service/http/indexer_service.rs index c095725d9..d3eb5e0a9 100644 --- a/common/src/indexer_service/http/indexer_service.rs +++ b/common/src/indexer_service/http/indexer_service.rs @@ -180,8 +180,14 @@ impl IndexerService { { let metrics = IndexerServiceMetrics::new(options.metrics_prefix); + let http_client = reqwest::Client::builder() + .tcp_nodelay(true) + .timeout(Duration::from_secs(30)) + .build() + .expect("Failed to init HTTP client"); + let network_subgraph = Box::leak(Box::new(SubgraphClient::new( - reqwest::Client::new(), + http_client.clone(), options .config .graph_node @@ -223,7 +229,7 @@ impl IndexerService { ); let escrow_subgraph = Box::leak(Box::new(SubgraphClient::new( - reqwest::Client::new(), + http_client, options .config .graph_node diff --git a/common/src/lib.rs b/common/src/lib.rs index 4fac5d546..287a22ac1 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -24,6 +24,6 @@ pub mod prelude { }; pub use super::escrow_accounts::escrow_accounts; pub use super::indexer_errors; - pub use super::subgraph_client::{DeploymentDetails, SubgraphClient}; + pub use super::subgraph_client::{DeploymentDetails, Query, QueryVariables, SubgraphClient}; pub use super::tap_manager::TapManager; } diff --git a/common/src/subgraph_client/client.rs b/common/src/subgraph_client/client.rs index d811ebd2f..aaf3c990b 100644 --- a/common/src/subgraph_client/client.rs +++ b/common/src/subgraph_client/client.rs @@ -3,15 +3,77 @@ use anyhow::anyhow; use eventuals::Eventual; -use graphql::http::Response; +use graphql_http::{ + graphql::{Document, IntoDocument}, + http::request::{IntoRequestParameters, RequestParameters}, + http_client::{ReqwestExt, ResponseResult}, +}; use reqwest::{header, Url}; use serde::de::Deserialize; -use serde_json::Value; +use serde_json::{Map, Value}; use toolshed::thegraph::DeploymentId; use tracing::warn; use super::monitor::{monitor_deployment_status, DeploymentStatus}; +#[derive(Clone)] +pub struct Query { + pub query: Document, + pub variables: Map, +} + +impl Query { + pub fn new(query: &str) -> Self { + Self { + query: query.into_document(), + variables: Map::default(), + } + } + + pub fn new_with_variables( + query: impl IntoDocument, + variables: impl Into, + ) -> Self { + Self { + query: query.into_document(), + variables: variables.into().into(), + } + } +} + +pub struct QueryVariables(Map); + +impl<'a, T> From for QueryVariables +where + T: IntoIterator, +{ + fn from(variables: T) -> Self { + Self( + variables + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect::>(), + ) + } +} + +impl Into> for QueryVariables { + fn into(self) -> Map { + self.0 + } +} + +impl IntoRequestParameters for Query { + fn into_request_parameters(self) -> RequestParameters { + RequestParameters { + query: self.query.into_document(), + variables: self.variables, + extensions: Map::default(), + operation_name: None, + } + } +} + #[derive(Debug, Clone)] pub struct DeploymentDetails { pub deployment: Option, @@ -61,8 +123,8 @@ impl DeploymentClient { pub async fn query Deserialize<'de>>( &self, - body: &Value, - ) -> Result, anyhow::Error> { + query: impl IntoRequestParameters + Send, + ) -> Result, anyhow::Error> { if let Some(ref status) = self.status { let deployment_status = status.value().await.expect("reading deployment status"); @@ -77,13 +139,8 @@ impl DeploymentClient { Ok(self .http_client .post(self.query_url.as_ref()) - .json(body) .header(header::USER_AGENT, "indexer-common") - .header(header::CONTENT_TYPE, "application/json") - .send() - .await - .and_then(|response| response.error_for_status())? - .json::>() + .send_graphql(query) .await?) } } @@ -108,12 +165,12 @@ impl SubgraphClient { pub async fn query Deserialize<'de>>( &self, - body: &Value, - ) -> Result, anyhow::Error> { + query: impl IntoRequestParameters + Send + Clone, + ) -> Result, anyhow::Error> { // Try the local client first; if that fails, log the error and move on // to the remote client if let Some(ref local_client) = self.local_client { - match local_client.query(body).await { + match local_client.query(query.clone()).await { Ok(response) => return Ok(response), Err(err) => warn!( "Failed to query local subgraph deployment `{}`, trying remote deployment next: {}", @@ -123,7 +180,7 @@ impl SubgraphClient { } // Try the remote client - self.remote_client.query(body).await.map_err(|err| { + self.remote_client.query(query).await.map_err(|err| { warn!( "Failed to query remote subgraph deployment `{}`: {}", self.remote_client.query_url, err @@ -187,19 +244,19 @@ mod test { // Check that the response is valid JSON let result = network_subgraph_client() - .query::(&json!({ - "query": r#" - query { - graphNetwork(id: 1) { - currentEpoch - } - } - "#, - })) + .query::(Query::new( + r#" + query { + graphNetwork(id: 1) { + currentEpoch + } + } + "#, + )) .await .unwrap(); - assert!(result.data.is_some()); + assert!(result.is_ok()); } #[tokio::test] @@ -273,12 +330,13 @@ mod test { ); // Query the subgraph - let response: Response = client - .query(&json!({ "query": "{ user(id: 1} { name } }"})) + let data = client + .query::(Query::new("{ user(id: 1} { name } }")) .await - .unwrap(); + .expect("Query should succeed") + .expect("Query result should have a value"); - assert_eq!(response.data, Some(json!({ "user": { "name": "local" } }))); + assert_eq!(data, json!({ "user": { "name": "local" } })); } #[tokio::test] @@ -352,12 +410,13 @@ mod test { ); // Query the subgraph - let response: Response = client - .query(&json!({ "query": "{ user(id: 1} { name } }"})) + let data = client + .query::(Query::new("{ user(id: 1} { name } }")) .await - .unwrap(); + .expect("Query should succeed") + .expect("Query result should have a value"); - assert_eq!(response.data, Some(json!({ "user": { "name": "remote" } }))); + assert_eq!(data, json!({ "user": { "name": "remote" } })); } #[tokio::test] @@ -431,11 +490,12 @@ mod test { ); // Query the subgraph - let response: Response = client - .query(&json!({ "query": "{ user(id: 1} { name } }"})) + let data = client + .query::(Query::new("{ user(id: 1} { name } }")) .await - .unwrap(); + .expect("Query should succeed") + .expect("Query result should have a value"); - assert_eq!(response.data, Some(json!({ "user": { "name": "remote" } }))); + assert_eq!(data, json!({ "user": { "name": "remote" } })); } } diff --git a/common/src/subgraph_client/mod.rs b/common/src/subgraph_client/mod.rs index 36dca7503..30d31a3de 100644 --- a/common/src/subgraph_client/mod.rs +++ b/common/src/subgraph_client/mod.rs @@ -4,4 +4,4 @@ mod client; mod monitor; -pub use client::{DeploymentDetails, SubgraphClient}; +pub use client::{DeploymentDetails, Query, QueryVariables, SubgraphClient}; diff --git a/common/src/subgraph_client/monitor.rs b/common/src/subgraph_client/monitor.rs index c638fdddc..d8a0b8b79 100644 --- a/common/src/subgraph_client/monitor.rs +++ b/common/src/subgraph_client/monitor.rs @@ -4,8 +4,8 @@ use std::time::Duration; use eventuals::{timer, Eventual, EventualExt}; -use graphql::http::Response; -use reqwest::{header, Url}; +use graphql_http::http_client::{ReqwestExt, ResponseResult}; +use reqwest::Url; use serde::Deserialize; use serde_json::{json, Value}; use tokio::time::sleep; @@ -27,16 +27,13 @@ pub struct DeploymentStatus { async fn query Deserialize<'de>>( url: Url, body: &Value, -) -> Result, reqwest::Error> { - reqwest::Client::new() +) -> Result, anyhow::Error> { + let serialized_body = serde_json::to_string(body)?; + + Ok(reqwest::Client::new() .post(url) - .json(body) - .header(header::CONTENT_TYPE, "application/json") - .send() - .await - .and_then(|response| response.error_for_status())? - .json::>() - .await + .send_graphql(serialized_body) + .await?) } pub fn monitor_deployment_status( @@ -68,23 +65,11 @@ pub fn monitor_deployment_status( format!("Failed to query status of deployment `{deployment}`: {e}") })?; - if let Some(errors) = response.errors { - warn!( - "Errors encountered querying the deployment status for `{}`: {}", - deployment, - errors - .into_iter() - .map(|e| e.message) - .collect::>() - .join(", ") - ); - } - - response - .data - .and_then(|data| data.indexing_statuses) - .and_then(|data| data.get(0).map(Clone::clone)) - .ok_or_else(|| format!("Deployment `{}` not found", deployment)) + response.map_err(|e| format!("{e}")).and_then(|data| { + data.indexing_statuses + .and_then(|statuses| statuses.get(0).map(Clone::clone)) + .ok_or_else(|| format!("Deployment `{deployment}` not found")) + }) } }, move |err: String| async move { diff --git a/service/Cargo.toml b/service/Cargo.toml index ae0cb4915..2c0f1253f 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -10,8 +10,8 @@ license = "Apache-2.0" [dependencies] indexer-common = { path = "../common" } confy = "0.5.1" -ethers-core = "2.0.10" -ethers = "2.0.10" +ethers-core = "2.0.11" +ethers = "2.0.11" eventuals = "0.6.7" dotenvy = "0.15" log = "0.4.17" @@ -22,7 +22,7 @@ tracing = "0.1.34" thiserror = "1.0.49" serde = { version = "1.0", features = ["rc", "derive"] } serde_json = "1" -axum = "0.5" +axum = "0.6.20" hyper = "0.14.27" tower = { version = "0.4", features = ["util", "timeout", "limit"] } tower-http = { version = "0.4.0", features = [ @@ -30,10 +30,9 @@ tower-http = { version = "0.4.0", features = [ "trace", "cors", ] } -toml = "0.7.4" once_cell = "1.17" -async-graphql = "4.0.16" -async-graphql-axum = "4.0.16" +async-graphql = "6.0.11" +async-graphql-axum = "6.0.11" sha3 = "0.10.6" tracing-subscriber = { version = "0.3", features = [ "env-filter", @@ -58,10 +57,17 @@ sqlx = { version = "0.7.1", features = [ alloy-primitives = { version = "0.4.2", features = ["serde"] } alloy-sol-types = "0.4.2" lazy_static = "1.4.0" -toolshed = { git = "https://github.com/edgeandnode/toolshed", branch = "main", features = [ - "graphql", +toolshed = { git = "https://github.com/edgeandnode/toolshed", branch = "main" } +graphql = { git = "https://github.com/edgeandnode/toolshed", branch = "main" } +graphql-http = { git = "https://github.com/edgeandnode/toolshed", branch = "main", features = [ + "http-reqwest", ] } build-info = "0.0.34" +figment = { version = "0.10", features = ["toml", "env"] } + +# FIXME: Needed due to a serde_spanned version conflict between +# `ethers` and `figment`. +serde_spanned = "=0.6.4" [dev-dependencies] faux = "0.1.10" diff --git a/service/src/cli.rs b/service/src/cli.rs new file mode 100644 index 000000000..e576e744a --- /dev/null +++ b/service/src/cli.rs @@ -0,0 +1,9 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Parser)] +pub struct Cli { + #[arg(long, value_name = "FILE")] + pub config: PathBuf, +} diff --git a/service/src/common/address.rs b/service/src/common/address.rs deleted file mode 100644 index 4e2232c78..000000000 --- a/service/src/common/address.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use ethers::signers::{ - coins_bip39::English, LocalWallet, MnemonicBuilder, Signer, Wallet, WalletError, -}; -use ethers_core::{k256::ecdsa::SigningKey, utils::hex}; -use sha3::{Digest, Keccak256}; - -/// A normalized address in checksum format. -pub type Address = String; - -/// Converts an address to checksum format and returns a typed instance. -pub fn to_address(s: impl AsRef) -> Address { - let address = s.as_ref().to_ascii_lowercase(); - let hash = &Keccak256::digest(address); - hex::encode(hash) -} - -/// Build Wallet from Private key or Mnemonic -pub fn build_wallet(value: &str) -> Result, WalletError> { - value - .parse::() - .or(MnemonicBuilder::::default().phrase(value).build()) -} - -/// Get wallet public address to String -pub fn wallet_address(wallet: &Wallet) -> String { - format!("{:?}", wallet.address()) -} diff --git a/service/src/common/database.rs b/service/src/common/database.rs deleted file mode 100644 index 5ba4707e8..000000000 --- a/service/src/common/database.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use sqlx::{postgres::PgPoolOptions, PgPool}; - -use std::time::Duration; -use tracing::debug; - -use crate::config; - -pub async fn connect(config: &config::Postgres) -> PgPool { - let url = format!( - "postgresql://{}:{}@{}:{}/{}", - config.postgres_username, - config.postgres_password, - config.postgres_host, - config.postgres_port, - config.postgres_database - ); - - debug!( - postgres_host = tracing::field::debug(&config.postgres_host), - postgres_port = tracing::field::debug(&config.postgres_port), - postgres_database = tracing::field::debug(&config.postgres_database), - "Connecting to database" - ); - - PgPoolOptions::new() - .max_connections(50) - .acquire_timeout(Duration::from_secs(3)) - .connect(&url) - .await - .expect("Could not connect to DATABASE_URL") -} diff --git a/service/src/common/mod.rs b/service/src/common/mod.rs deleted file mode 100644 index a7c9b560b..000000000 --- a/service/src/common/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -pub mod address; -pub mod database; -pub mod indexer_management; diff --git a/service/src/config.rs b/service/src/config.rs index c131a4f65..f8c61fb66 100644 --- a/service/src/config.rs +++ b/service/src/config.rs @@ -1,267 +1,245 @@ // Copyright 2023-, GraphOps and Semiotic Labs. // SPDX-License-Identifier: Apache-2.0 -use clap::{command, Args, Parser, ValueEnum}; +use std::path::PathBuf; use alloy_primitives::Address; +use figment::{ + providers::{Format, Toml}, + Figment, +}; +use indexer_common::indexer_service::http::IndexerServiceConfig; use serde::{Deserialize, Serialize}; use toolshed::thegraph::DeploymentId; -use crate::util::init_tracing; - -#[derive(Clone, Debug, Parser, Serialize, Deserialize, Default)] -#[clap( - name = "indexer-service", - about = "Indexer service on top of graph node", - author = "hopeyen" -)] -#[command(author, version, about, long_about = None, arg_required_else_help = true)] -pub struct Cli { - #[command(flatten)] - pub ethereum: Ethereum, - #[command(flatten)] - pub receipts: Receipts, - #[command(flatten)] - pub indexer_infrastructure: IndexerInfrastructure, - #[command(flatten)] - pub postgres: Postgres, - #[command(flatten)] - pub network_subgraph: NetworkSubgraph, - #[command(flatten)] - pub escrow_subgraph: EscrowSubgraph, - - #[arg( - short, - value_name = "config", - env = "CONFIG", - help = "Indexer service configuration file (YAML format)" - )] - config: Option, +#[derive(Clone, Debug, Deserialize)] +pub struct Config { + // pub ethereum: Ethereum, + // pub receipts: Receipts, + // pub indexer_infrastructure: IndexerInfrastructure, + // pub postgres: Postgres, + // pub network_subgraph: NetworkSubgraph, + // pub escrow_subgraph: EscrowSubgraph, + pub common: IndexerServiceConfig, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct Ethereum { - #[clap( - long, - value_name = "ethereum-node-provider", - env = "ETH_NODE", - help = "Ethereum node or provider URL" - )] + // #[clap( + // long, + // value_name = "ethereum-node-provider", + // env = "ETH_NODE", + // help = "Ethereum node or provider URL" + // )] pub ethereum: String, - #[clap( - long, - value_name = "ethereum-polling-interval", - env = "ETHEREUM_POLLING_INTERVAL", - default_value_t = 4000, - help = "Polling interval for the Ethereum provider (ms)" - )] + // #[clap( + // long, + // value_name = "ethereum-polling-interval", + // env = "ETHEREUM_POLLING_INTERVAL", + // default_value_t = 4000, + // help = "Polling interval for the Ethereum provider (ms)" + // )] pub ethereum_polling_interval: usize, - #[clap( - long, - value_name = "mnemonic", - env = "MNEMONIC", - help = "Mnemonic for the operator wallet" - )] + // #[clap( + // long, + // value_name = "mnemonic", + // env = "MNEMONIC", + // help = "Mnemonic for the operator wallet" + // )] pub mnemonic: String, - #[clap( - long, - value_name = "indexer-address", - env = "INDEXER_ADDRESS", - help = "Ethereum address of the indexer" - )] + // #[clap( + // long, + // value_name = "indexer-address", + // env = "INDEXER_ADDRESS", + // help = "Ethereum address of the indexer" + // )] pub indexer_address: Address, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct Receipts { - #[clap( - long, - value_name = "receipts-verifier-chain-id", - env = "RECEIPTS_VERIFIER_CHAIN_ID", - help = "Scalar TAP verifier chain ID" - )] + // #[clap( + // long, + // value_name = "receipts-verifier-chain-id", + // env = "RECEIPTS_VERIFIER_CHAIN_ID", + // help = "Scalar TAP verifier chain ID" + // )] pub receipts_verifier_chain_id: u64, - #[clap( - long, - value_name = "receipts-verifier-address", - env = "RECEIPTS_VERIFIER_ADDRESS", - help = "Scalar TAP verifier contract address" - )] + // #[clap( + // long, + // value_name = "receipts-verifier-address", + // env = "RECEIPTS_VERIFIER_ADDRESS", + // help = "Scalar TAP verifier contract address" + // )] pub receipts_verifier_address: Address, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct IndexerInfrastructure { - #[clap( - long, - value_name = "port", - env = "PORT", - default_value_t = 7600, - help = "Port to serve queries at" - )] + // #[clap( + // long, + // value_name = "port", + // env = "PORT", + // default_value_t = 7600, + // help = "Port to serve queries at" + // )] pub port: u32, - #[clap( - long, - value_name = "metrics-port", - env = "METRICS_PORT", - default_value_t = 7300, - help = "Port to serve Prometheus metrics at" - )] + // #[clap( + // long, + // value_name = "metrics-port", + // env = "METRICS_PORT", + // default_value_t = 7300, + // help = "Port to serve Prometheus metrics at" + // )] pub metrics_port: u16, - #[clap( - long, - value_name = "graph-node-query-endpoint", - env = "GRAPH_NODE_QUERY_ENDPOINT", - default_value_t = String::from("http://0.0.0.0:8000"), - help = "Graph node GraphQL HTTP service endpoint" - )] + // #[clap( + // long, + // value_name = "graph-node-query-endpoint", + // env = "GRAPH_NODE_QUERY_ENDPOINT", + // default_value_t = String::from("http://0.0.0.0:8000"), + // help = "Graph node GraphQL HTTP service endpoint" + // )] pub graph_node_query_endpoint: String, - #[clap( - long, - value_name = "graph-node-status-endpoint", - env = "GRAPH_NODE_STATUS_ENDPOINT", - default_value_t = String::from("http://0.0.0.0:8030"), - help = "Graph node endpoint for the index node server" - )] + // #[clap( + // long, + // value_name = "graph-node-status-endpoint", + // env = "GRAPH_NODE_STATUS_ENDPOINT", + // default_value_t = String::from("http://0.0.0.0:8030"), + // help = "Graph node endpoint for the index node server" + // )] pub graph_node_status_endpoint: String, - #[clap( - long, - value_name = "log-level", - env = "LOG_LEVEL", - value_enum, - help = "Log level in RUST_LOG format" - )] + // #[clap( + // long, + // value_name = "log-level", + // env = "LOG_LEVEL", + // value_enum, + // help = "Log level in RUST_LOG format" + // )] pub log_level: Option, - #[clap( - long, - value_name = "gcloud-profiling", - env = "GCLOUD_PROFILING", - default_value_t = false, - help = "Whether to enable Google Cloud profiling" - )] + // #[clap( + // long, + // value_name = "gcloud-profiling", + // env = "GCLOUD_PROFILING", + // default_value_t = false, + // help = "Whether to enable Google Cloud profiling" + // )] pub gcloud_profiling: bool, - #[clap( - long, - value_name = "free-query-auth-token", - env = "FREE_QUERY_AUTH_TOKEN", - help = "Auth token that clients can use to query for free" - )] + // #[clap( + // long, + // value_name = "free-query-auth-token", + // env = "FREE_QUERY_AUTH_TOKEN", + // help = "Auth token that clients can use to query for free" + // )] pub free_query_auth_token: Option, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct Postgres { - #[clap( - long, - value_name = "postgres-host", - env = "POSTGRES_HOST", - default_value_t = String::from("http://0.0.0.0/"), - help = "Postgres host" - )] + // #[clap( + // long, + // value_name = "postgres-host", + // env = "POSTGRES_HOST", + // default_value_t = String::from("http://0.0.0.0/"), + // help = "Postgres host" + // )] pub postgres_host: String, - #[clap( - long, - value_name = "postgres-port", - env = "POSTGRES_PORT", - default_value_t = 5432, - help = "Postgres port" - )] + // #[clap( + // long, + // value_name = "postgres-port", + // env = "POSTGRES_PORT", + // default_value_t = 5432, + // help = "Postgres port" + // )] pub postgres_port: usize, - #[clap( - long, - value_name = "postgres-database", - env = "POSTGRES_DATABASE", - help = "Postgres database name" - )] + // #[clap( + // long, + // value_name = "postgres-database", + // env = "POSTGRES_DATABASE", + // help = "Postgres database name" + // )] pub postgres_database: String, - #[clap( - long, - value_name = "postgres-username", - env = "POSTGRES_USERNAME", - default_value_t = String::from("postgres"), - help = "Postgres username" - )] + // #[clap( + // long, + // value_name = "postgres-username", + // env = "POSTGRES_USERNAME", + // default_value_t = String::from("postgres"), + // help = "Postgres username" + // )] pub postgres_username: String, - #[clap( - long, - value_name = "postgres-password", - env = "POSTGRES_PASSWORD", - default_value_t = String::from(""), - help = "Postgres password" - )] + // #[clap( + // long, + // value_name = "postgres-password", + // env = "POSTGRES_PASSWORD", + // default_value_t = String::from(""), + // help = "Postgres password" + // )] pub postgres_password: String, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct NetworkSubgraph { - #[clap( - long, - value_name = "network-subgraph-deployment", - env = "NETWORK_SUBGRAPH_DEPLOYMENT", - help = "Network subgraph deployment" - )] + // #[clap( + // long, + // value_name = "network-subgraph-deployment", + // env = "NETWORK_SUBGRAPH_DEPLOYMENT", + // help = "Network subgraph deployment" + // )] pub network_subgraph_deployment: Option, - #[clap( - long, - value_name = "network-subgraph-endpoint", - env = "NETWORK_SUBGRAPH_ENDPOINT", - default_value_t = String::from("https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"), - help = "Endpoint to query the network subgraph from" - )] + // #[clap( + // long, + // value_name = "network-subgraph-endpoint", + // env = "NETWORK_SUBGRAPH_ENDPOINT", + // default_value_t = String::from("https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"), + // help = "Endpoint to query the network subgraph from" + // )] pub network_subgraph_endpoint: String, - #[clap( - long, - value_name = "network-subgraph-auth-token", - env = "NETWORK_SUBGRAPH_AUTH_TOKEN", - help = "Bearer token to require for /network queries" - )] + // #[clap( + // long, + // value_name = "network-subgraph-auth-token", + // env = "NETWORK_SUBGRAPH_AUTH_TOKEN", + // help = "Bearer token to require for /network queries" + // )] pub network_subgraph_auth_token: Option, - #[clap( - long, - value_name = "serve-network-subgraph", - env = "SERVE_NETWORK_SUBGRAPH", - default_value_t = false, - help = "Whether to serve the network subgraph at /network" - )] + // #[clap( + // long, + // value_name = "serve-network-subgraph", + // env = "SERVE_NETWORK_SUBGRAPH", + // default_value_t = false, + // help = "Whether to serve the network subgraph at /network" + // )] pub serve_network_subgraph: bool, - #[clap( - long, - value_name = "allocation-syncing-interval", - env = "ALLOCATION_SYNCING_INTERVAL", - default_value_t = 120_000, - help = "Interval (in ms) for syncing indexer allocations from the network" - )] + // #[clap( + // long, + // value_name = "allocation-syncing-interval", + // env = "ALLOCATION_SYNCING_INTERVAL", + // default_value_t = 120_000, + // help = "Interval (in ms) for syncing indexer allocations from the network" + // )] pub allocation_syncing_interval: u64, - #[clap( - long, - value_name = "client-signer-address", - env = "CLIENT_SIGNER_ADDRESS", - help = "Address that signs query fee receipts from a known client" - )] + // #[clap( + // long, + // value_name = "client-signer-address", + // env = "CLIENT_SIGNER_ADDRESS", + // help = "Address that signs query fee receipts from a known client" + // )] pub client_signer_address: Option, } -#[derive(Clone, Debug, Args, Serialize, Deserialize, Default)] -#[group(required = true, multiple = true)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct EscrowSubgraph { - #[clap( - long, - value_name = "escrow-subgraph-deployment", - env = "ESCROW_SUBGRAPH_DEPLOYMENT", - help = "Escrow subgraph deployment" - )] + // #[clap( + // long, + // value_name = "escrow-subgraph-deployment", + // env = "ESCROW_SUBGRAPH_DEPLOYMENT", + // help = "Escrow subgraph deployment" + // )] pub escrow_subgraph_deployment: Option, - #[clap( - long, - value_name = "escrow-subgraph-endpoint", - env = "ESCROW_SUBGRAPH_ENDPOINT", - help = "Endpoint to query the network subgraph from" - )] + // #[clap( + // long, + // value_name = "escrow-subgraph-endpoint", + // env = "ESCROW_SUBGRAPH_ENDPOINT", + // help = "Endpoint to query the network subgraph from" + // )] pub escrow_subgraph_endpoint: String, // #[clap( // long, @@ -288,39 +266,8 @@ pub struct EscrowSubgraph { pub escrow_syncing_interval: u64, } -impl Cli { - /// Parse config arguments - /// If environmental variable for config is set to a valid config file path, then parse from config - /// Otherwise parse from command line arguments - pub fn args() -> Self { - let cli = if let Ok(file_path) = std::env::var("config") { - confy::load_path::(file_path.clone()) - .unwrap_or_else(|_| panic!("Parse config file at {}", file_path.clone())) - } else { - Cli::parse() - // Potentially store it for the user - // let _ = confy::store_path("./args.toml", cli.clone()); - }; - - // Enables tracing under RUST_LOG variable - if let Some(log_setting) = &cli.indexer_infrastructure.log_level { - std::env::set_var("RUST_LOG", log_setting); - }; - // add a LogFormat to config - init_tracing("pretty".to_string()).expect("Could not set up global default subscriber for logger, check environmental variable `RUST_LOG` or the CLI input `log-level`"); - cli +impl Config { + pub fn load(filename: &PathBuf) -> Result { + Figment::new().merge(Toml::file(filename)).extract() } } - -#[derive( - Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize, Default, -)] -pub enum LogLevel { - Trace, - #[default] - Debug, - Info, - Warn, - Error, - Fatal, -} diff --git a/service/src/common/indexer_management/mod.rs b/service/src/database.rs similarity index 97% rename from service/src/common/indexer_management/mod.rs rename to service/src/database.rs index 32a19e12a..96487ff59 100644 --- a/service/src/common/indexer_management/mod.rs +++ b/service/src/database.rs @@ -1,12 +1,25 @@ // Copyright 2023-, GraphOps and Semiotic Labs. // SPDX-License-Identifier: Apache-2.0 +use std::time::Duration; use std::{collections::HashSet, str::FromStr}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use sqlx::PgPool; +use sqlx::{postgres::PgPoolOptions, PgPool}; use toolshed::thegraph::{DeploymentId, DeploymentIdError}; +use tracing::debug; + +pub async fn connect(url: &str) -> PgPool { + debug!("Connecting to database"); + + PgPoolOptions::new() + .max_connections(50) + .acquire_timeout(Duration::from_secs(3)) + .connect(&url) + .await + .expect("Should be able to connect to the database") +} /// Internal cost model representation as stored in the database. /// diff --git a/service/src/graph_node.rs b/service/src/graph_node.rs deleted file mode 100644 index 7c875764f..000000000 --- a/service/src/graph_node.rs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::anyhow; -use reqwest::{header, Client, Url}; -use std::sync::Arc; -use toolshed::thegraph::DeploymentId; - -use crate::query_processor::{QueryError, UnattestedQueryResult}; - -/// Graph node query wrapper. -/// -/// This is Arc internally, so it can be cloned and shared between threads. -#[derive(Debug, Clone)] -pub struct GraphNodeInstance { - client: Client, // it is Arc - subgraphs_base_url: Arc, -} - -impl GraphNodeInstance { - pub fn new(endpoint: &str) -> GraphNodeInstance { - let subgraphs_base_url = Url::parse(endpoint) - .and_then(|u| u.join("/subgraphs/id/")) - .expect("Could not parse graph node endpoint"); - let client = reqwest::Client::builder() - .user_agent("indexer-service") - .build() - .expect("Could not build a client to graph node query endpoint"); - GraphNodeInstance { - client, - subgraphs_base_url: Arc::new(subgraphs_base_url), - } - } - - pub async fn subgraph_query_raw( - &self, - subgraph_id: &DeploymentId, - data: String, - ) -> Result { - let request = self - .client - .post( - self.subgraphs_base_url - .join(&subgraph_id.to_string()) - .map_err(|e| { - QueryError::Other(anyhow!( - "Could not build subgraph query URL: {}", - e.to_string() - )) - })?, - ) - .body(data) - .header(header::CONTENT_TYPE, "application/json"); - - let response = request.send().await?; - let attestable = response - .headers() - .get("graph-attestable") - .map_or(false, |v| v == "true"); - - Ok(UnattestedQueryResult { - graphql_response: response.text().await?, - attestable, - }) - } -} - -#[cfg(test)] -mod test { - use std::str::FromStr; - - use lazy_static::lazy_static; - use serde_json::json; - use wiremock::matchers::{method, path}; - use wiremock::{Mock, MockServer, ResponseTemplate}; - - use super::*; - - lazy_static! { - static ref NETWORK_SUBGRAPH_ID: DeploymentId = - DeploymentId::from_str("QmV614UpBCpuusv5MsismmPYu4KqLtdeNMKpiNrX56kw6u").unwrap(); - } - - async fn mock_graph_node_server() -> MockServer { - let mock_server = MockServer::start().await; - let mock = Mock::given(method("POST")) - .and(path( - "/subgraphs/id/".to_string() + &NETWORK_SUBGRAPH_ID.to_string(), - )) - .respond_with(ResponseTemplate::new(200).set_body_raw( - r#" - { - "data": { - "graphNetwork": { - "currentEpoch": 960 - } - } - } - "#, - "application/json", - )); - mock_server.register(mock).await; - - mock_server - } - - async fn local_graph_node() -> GraphNodeInstance { - let graph_node_endpoint = std::env::var("GRAPH_NODE_ENDPOINT") - .expect("GRAPH_NODE_ENDPOINT env variable is not set"); - - GraphNodeInstance::new(&graph_node_endpoint) - } - - /// Also tests against the network subgraph, but using the `subgraph_query_raw` method - #[tokio::test] - #[ignore] // Run only if explicitly specified - async fn test_subgraph_query_local() { - let network_subgraph_id = DeploymentId::from_str( - &std::env::var("NETWORK_SUBGRAPH_ID") - .expect("NETWORK_SUBGRAPH_ID env variable is not set"), - ) - .unwrap(); - - let graph_node = local_graph_node().await; - - let query = r#" - query { - graphNetwork(id: 1) { - currentEpoch - } - } - "#; - - let query_json = json!({ - "query": query, - "variables": {} - }); - - let response = graph_node - .subgraph_query_raw(&network_subgraph_id, query_json.to_string()) - .await - .unwrap(); - - // Check that the response is valid JSON - let _json: serde_json::Value = serde_json::from_str(&response.graphql_response).unwrap(); - } - - /// Also tests against the network subgraph, but using the `subgraph_query_raw` method - #[tokio::test] - async fn test_subgraph_query() { - let mock_server = mock_graph_node_server().await; - - let graph_node = GraphNodeInstance::new(&mock_server.uri()); - - let query = r#" - query { - graphNetwork(id: 1) { - currentEpoch - } - } - "#; - - let query_json = json!({ - "query": query, - "variables": {} - }); - - let response = graph_node - .subgraph_query_raw(&NETWORK_SUBGRAPH_ID, query_json.to_string()) - .await - .unwrap(); - - // Check that the response is valid JSON - let _json: serde_json::Value = serde_json::from_str(&response.graphql_response).unwrap(); - } -} diff --git a/service/src/main.rs b/service/src/main.rs index 064ea5071..894e8dce7 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -1,198 +1,182 @@ // Copyright 2023-, GraphOps and Semiotic Labs. // SPDX-License-Identifier: Apache-2.0 -use alloy_sol_types::eip712_domain; -use axum::Server; -use dotenvy::dotenv; -use ethereum_types::U256; -use std::{net::SocketAddr, str::FromStr, time::Duration}; -use tracing::info; - -use indexer_common::{ - indexer_service::http::IndexerServiceRelease, - prelude::{ - attestation_signers, dispute_manager, escrow_accounts, indexer_allocations, - DeploymentDetails, SubgraphClient, TapManager, - }, +use std::sync::Arc; +use std::time::Duration; + +use anyhow::Error; +use axum::{ + async_trait, + response::{IntoResponse, Response}, + routing::post, + Json, Router, }; +use clap::Parser; +use indexer_common::indexer_service::http::{ + IndexerService, IndexerServiceImpl, IndexerServiceOptions, IndexerServiceRelease, IsAttestable, +}; +use reqwest::StatusCode; +use serde::Serialize; +use serde_json::{json, Value}; +use sqlx::PgPool; +use thiserror::Error; +use toolshed::thegraph::DeploymentId; +use tracing::error; + +mod cli; +mod config; +pub mod database; +mod routes; + +use cli::Cli; +use config::Config; + +#[derive(Debug, Error)] +pub enum SubgraphServiceError { + #[error("Invalid status query: {0}")] + InvalidStatusQuery(Error), + #[error("Unsupported status query fields: {0:?}")] + UnsupportedStatusQueryFields(Vec), + #[error("Internal server error: {0}")] + StatusQueryError(Error), +} -use util::shutdown_signal; +impl From<&SubgraphServiceError> for StatusCode { + fn from(err: &SubgraphServiceError) -> Self { + use SubgraphServiceError::*; + match err { + InvalidStatusQuery(_) => StatusCode::BAD_REQUEST, + UnsupportedStatusQueryFields(_) => StatusCode::BAD_REQUEST, + StatusQueryError(_) => StatusCode::INTERNAL_SERVER_ERROR, + } + } +} -use crate::{ - common::database, config::Cli, metrics::handle_serve_metrics, query_processor::QueryProcessor, - server::create_server, util::public_key, -}; +// Tell axum how to convert `SubgraphServiceError` into a response. +impl IntoResponse for SubgraphServiceError { + fn into_response(self) -> Response { + (StatusCode::from(&self), self.to_string()).into_response() + } +} -use server::ServerOptions; +#[derive(Serialize)] +#[serde(transparent)] +struct SubgraphResponse { + inner: Value, + #[serde(skip)] + attestable: bool, +} -mod common; -mod config; -mod graph_node; -mod metrics; -mod query_processor; -mod server; -mod util; - -#[cfg(test)] -mod test_vectors; - -/// Create Indexer service App -/// -/// Initialization for server and Query processor -/// -/// Validate that graph-node instance is running for Query processor -/// Validate that server is running with a health check -/// -/// Parse Requests received -/// -/// Route the requests as a FreeQuery -/// -/// Return response from Query Processor +impl SubgraphResponse { + fn new(inner: Value, attestable: bool) -> Self { + Self { inner, attestable } + } +} + +impl IntoResponse for SubgraphResponse { + fn into_response(self) -> Response { + Json(self.inner).into_response() + } +} + +impl IsAttestable for SubgraphResponse { + fn is_attestable(&self) -> bool { + self.attestable + } +} + +pub struct SubgraphServiceState { + pub config: Config, + pub database: PgPool, + pub cost_schema: routes::cost::CostSchema, + pub graph_node_client: reqwest::Client, + pub graph_node_status_url: String, +} + +struct SubgraphService { + config: Config, +} + +impl SubgraphService { + fn new(config: Config) -> Self { + Self { config } + } +} + +#[async_trait] +impl IndexerServiceImpl for SubgraphService { + type Error = SubgraphServiceError; + type Request = serde_json::Value; + type Response = SubgraphResponse; + type State = SubgraphServiceState; + + async fn process_request( + &self, + _manifest_id: DeploymentId, + request: Self::Request, + ) -> Result<(Self::Request, Self::Response), Self::Error> { + Ok((request, SubgraphResponse::new(json!("hello"), false))) + } +} + +/// Run the subgraph indexer service #[tokio::main] -async fn main() -> Result<(), std::io::Error> { - dotenv().ok(); +async fn main() -> Result<(), Error> { + tracing_subscriber::fmt::init(); + + // Parse command line and environment arguments + let cli = Cli::parse(); + + // Load the json-rpc service configuration, which is a combination of the + // general configuration options for any indexer service and specific + // options added for JSON-RPC + let config = match Config::load(&cli.config) { + Ok(config) => config, + Err(e) => { + error!( + "Invalid configuration file `{}`: {}", + cli.config.display(), + e + ); + std::process::exit(1); + } + }; // Parse basic configurations - let config = Cli::args(); build_info::build_info!(fn build_info); let release = IndexerServiceRelease::from(build_info()); - // Initialize graph-node client - let graph_node = graph_node::GraphNodeInstance::new( - &config.indexer_infrastructure.graph_node_query_endpoint, - ); - - let http_client = reqwest::Client::builder() - .tcp_nodelay(true) - .timeout(Duration::from_secs(30)) - .build() - .expect("Failed to init HTTP client"); - - // Make an instance of network subgraph at either - // graph_node_query_endpoint/subgraphs/id/network_subgraph_deployment - // or network_subgraph_endpoint - // - // We're leaking the network subgraph here to obtain a reference with - // a static lifetime, which avoids having to pass around and clone `Arc` - // objects everywhere. Since the network subgraph is read-only, this is - // no problem. - let network_subgraph = Box::leak(Box::new(SubgraphClient::new( - http_client.clone(), - config - .network_subgraph - .network_subgraph_deployment - .map(|deployment| { - DeploymentDetails::for_graph_node( - &config.indexer_infrastructure.graph_node_status_endpoint, - &config.indexer_infrastructure.graph_node_query_endpoint, - deployment, - ) - }) - .transpose() - .expect("Failed to parse graph node query endpoint and network subgraph deployment"), - DeploymentDetails::for_query_url(&config.network_subgraph.network_subgraph_endpoint) - .expect("Failed to parse network subgraph endpoint"), - ))); - - let indexer_allocations = indexer_allocations( - network_subgraph, - config.ethereum.indexer_address, - 1, - Duration::from_millis(config.network_subgraph.allocation_syncing_interval), - ); - - // TODO: Chain ID should be a config - let graph_network_id = 1; - - let dispute_manager = - dispute_manager(network_subgraph, graph_network_id, Duration::from_secs(60)); - - let attestation_signers = attestation_signers( - indexer_allocations.clone(), - config.ethereum.mnemonic.clone(), - U256::from(graph_network_id), - dispute_manager, - ); - - // Establish Database connection necessary for serving indexer management - // requests with defined schema - // Note: Typically, you'd call `sqlx::migrate!();` here to sync the models - // which defaults to files in "./migrations" to sync the database; - // however, this can cause conflicts with the migrations run by indexer - // agent. Hence we leave syncing and migrating entirely to the agent and - // assume the models are up to date in the service. - let indexer_management_db = database::connect(&config.postgres).await; - - let escrow_subgraph = Box::leak(Box::new(SubgraphClient::new( - http_client, - config - .escrow_subgraph - .escrow_subgraph_deployment - .map(|deployment| { - DeploymentDetails::for_graph_node( - &config.indexer_infrastructure.graph_node_status_endpoint, - &config.indexer_infrastructure.graph_node_query_endpoint, - deployment, - ) - }) - .transpose() - .expect("Failed to parse graph node query endpoint and escrow subgraph deployment"), - DeploymentDetails::for_query_url(&config.escrow_subgraph.escrow_subgraph_endpoint) - .expect("Failed to parse escrow subgraph endpoint"), - ))); - - let escrow_accounts = escrow_accounts( - escrow_subgraph, - config.ethereum.indexer_address, - Duration::from_millis(config.escrow_subgraph.escrow_syncing_interval), - ); - - let tap_manager = TapManager::new( - indexer_management_db.clone(), - indexer_allocations, - escrow_accounts, - eip712_domain! { - name: "Scalar TAP", - version: "1", - chain_id: config.receipts.receipts_verifier_chain_id, - verifying_contract: config.receipts.receipts_verifier_address, - }, - ); - // Proper initiation of server, query processor - // server health check, graph-node instance connection check - let query_processor = - QueryProcessor::new(graph_node.clone(), attestation_signers.clone(), tap_manager); - - // Start indexer service basic metrics - tokio::spawn(handle_serve_metrics( - String::from("0.0.0.0"), - config.indexer_infrastructure.metrics_port, - )); - - let service_options = ServerOptions::new( - Some(config.indexer_infrastructure.port), + // Some of the subgrpah service configuration goes into the so-called + // "state", which will be passed to any request handler, middleware etc. + // that is involved in serving requests + let state = Arc::new(SubgraphServiceState { + config: config.clone(), + database: database::connect(&config.common.database.postgres_url).await, + cost_schema: routes::cost::build_schema().await, + graph_node_client: reqwest::ClientBuilder::new() + .tcp_nodelay(true) + .timeout(Duration::from_secs(30)) + .build() + .expect("Failed to init HTTP client for Graph Node"), + graph_node_status_url: config + .common + .graph_node + .as_ref() + .expect("Config must have `common.graph_node.status_url` set") + .status_url + .clone(), + }); + + IndexerService::run(IndexerServiceOptions { release, - query_processor, - config.indexer_infrastructure.free_query_auth_token, - config.indexer_infrastructure.graph_node_status_endpoint, - indexer_management_db, - public_key(&config.ethereum.mnemonic).expect("Failed to initiate with operator wallet"), - network_subgraph, - config.network_subgraph.network_subgraph_auth_token, - config.network_subgraph.serve_network_subgraph, - ); - - info!("Initialized server options"); - let app = create_server(service_options).await; - - let addr = SocketAddr::from_str(&format!("0.0.0.0:{}", config.indexer_infrastructure.port)) - .expect("Start server port"); - info!("Initialized server app at {}", addr); - Server::bind(&addr) - .serve(app.into_make_service()) - .with_graceful_shutdown(shutdown_signal()) - .await - .unwrap(); - - Ok(()) + config: config.common.clone(), + url_namespace: "subgraphs", + metrics_prefix: "subgraph", + service_impl: SubgraphService::new(config), + extra_routes: Router::new() + .route("/cost", post(routes::cost::cost)) + .route("/status", post(routes::status)) + .with_state(state), + }) + .await } diff --git a/service/src/metrics/mod.rs b/service/src/metrics/mod.rs deleted file mode 100644 index dfc8d5628..000000000 --- a/service/src/metrics/mod.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use autometrics::{encode_global_metrics, global_metrics_exporter}; -use axum::http::StatusCode; -use axum::routing::get; -use axum::Router; -use lazy_static::lazy_static; -use prometheus::{register_histogram_vec, register_int_counter_vec, HistogramVec, IntCounterVec}; -use std::{net::SocketAddr, str::FromStr}; -use tracing::info; - -// Record Queries related metrics -lazy_static! { - pub static ref QUERIES: IntCounterVec = register_int_counter_vec!( - "indexer_service_queries_total", - "Incoming queries", - &["deployment"], - ) - .expect("Failed to create queries counters"); - pub static ref SUCCESSFUL_QUERIES: IntCounterVec = register_int_counter_vec!( - "indexer_service_queries_ok", - "Successfully executed queries", - &["deployment"], - ) - .expect("Failed to create successfulQueries counters"); - pub static ref FAILED_QUERIES: IntCounterVec = register_int_counter_vec!( - "indexer_service_queries_failed", - "Queries that failed to execute", - &["deployment"], - ) - .expect("Failed to create failedQueries counters"); - pub static ref QUERIES_WITH_INVALID_RECEIPT_HEADER: IntCounterVec = register_int_counter_vec!( - "indexer_service_queries_with_invalid_receipt_header", - "Queries that failed executing because they came with an invalid receipt header", - &["deployment"], - ) - .expect("Failed to create queriesWithInvalidReceiptHeader counters"); - pub static ref QUERIES_WITHOUT_RECEIPT: IntCounterVec = register_int_counter_vec!( - "indexer_service_queries_without_receipt", - "Queries that failed executing because they came without a receipt", - &["deployment"], - ) - .expect("Failed to create queriesWithoutReceipt counters"); - pub static ref QUERY_DURATION: HistogramVec = register_histogram_vec!( - "indexer_service_query_duration", - "Duration of processing a query from start to end", - &["deployment"], - ) - .unwrap(); -} - -/// This handler serializes the metrics into a string for Prometheus to scrape -pub async fn get_metrics() -> (StatusCode, String) { - match encode_global_metrics() { - Ok(metrics) => (StatusCode::OK, metrics), - Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{err:?}")), - } -} - -/// Metrics server router -pub async fn handle_serve_metrics(host: String, port: u16) { - // Set up the exporter to collect metrics - let _exporter = global_metrics_exporter(); - - let app = Router::new().route("/metrics", get(get_metrics)); - let addr = - SocketAddr::from_str(&format!("{}:{}", host, port)).expect("Start Prometheus metrics"); - let server = axum::Server::bind(&addr); - info!( - address = addr.to_string(), - "Prometheus Metrics port exposed" - ); - - server - .serve(app.into_make_service()) - .await - .expect("Error starting Prometheus metrics port"); -} diff --git a/service/src/query_processor.rs b/service/src/query_processor.rs deleted file mode 100644 index b4e99120c..000000000 --- a/service/src/query_processor.rs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use std::collections::HashMap; - -use alloy_primitives::Address; -use eventuals::Eventual; -use indexer_common::tap_manager::TapManager; -use log::error; -use serde::{Deserialize, Serialize}; -use tap_core::tap_manager::SignedReceipt; -use toolshed::thegraph::attestation::Attestation; -use toolshed::thegraph::DeploymentId; - -use indexer_common::indexer_errors::{IndexerError, IndexerErrorCause, IndexerErrorCode}; -use indexer_common::prelude::AttestationSigner; - -use crate::graph_node::GraphNodeInstance; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct QueryResult { - #[serde(rename = "graphQLResponse")] - pub graphql_response: String, - pub attestation: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct UnattestedQueryResult { - #[serde(rename = "graphQLResponse")] - pub graphql_response: String, - pub attestable: bool, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -pub struct Response { - pub result: T, - pub status: i64, -} - -/// Free query do not need signature, receipt, signers -/// Also ignore metrics for now -/// Later add along with PaidQuery -#[derive(Debug)] -pub struct FreeQuery { - pub subgraph_deployment_id: DeploymentId, - pub query: String, -} - -/// Paid query needs subgraph_deployment_id, query, receipt -pub struct PaidQuery { - pub subgraph_deployment_id: DeploymentId, - pub query: String, - pub receipt: String, -} - -#[derive(Debug, thiserror::Error)] -pub enum QueryError { - #[error(transparent)] - Transport(#[from] reqwest::Error), - #[error("The subgraph is in a failed state")] - IndexingError, - #[error("Bad or invalid entity data found in the subgraph: {}", .0.to_string())] - BadData(anyhow::Error), - #[error("Unknown error: {0}")] - Other(anyhow::Error), -} - -#[derive(Clone)] -pub struct QueryProcessor { - graph_node: GraphNodeInstance, - attestation_signers: Eventual>, - tap_manager: TapManager, -} - -impl QueryProcessor { - pub fn new( - graph_node: GraphNodeInstance, - attestation_signers: Eventual>, - tap_manager: TapManager, - ) -> QueryProcessor { - QueryProcessor { - graph_node, - attestation_signers, - tap_manager, - } - } - - pub async fn execute_free_query( - &self, - query: FreeQuery, - ) -> Result, QueryError> { - let response = self - .graph_node - .subgraph_query_raw(&query.subgraph_deployment_id, query.query) - .await?; - - Ok(Response { - result: response, - status: 200, - }) - } - - pub async fn execute_paid_query( - &self, - query: PaidQuery, - ) -> Result, QueryError> { - let PaidQuery { - subgraph_deployment_id, - query, - receipt, - } = query; - - let parsed_receipt: SignedReceipt = match serde_json::from_str(&receipt) - .map_err(|e| QueryError::Other(anyhow::Error::from(e))) - { - Ok(r) => r, - Err(e) => { - IndexerError::new( - IndexerErrorCode::IE031, - Some(IndexerErrorCause::new( - "Failed to parse receipt for a paid query", - )), - ); - - return Err(e); - } - }; - - let allocation_id = parsed_receipt.message.allocation_id; - - self.tap_manager - .verify_and_store_receipt(parsed_receipt) - .await - .map_err(|e| { - IndexerError::new( - IndexerErrorCode::IE053, - Some(IndexerErrorCause::new( - "Failed to verify and store a parsed receipt", - )), - ); - - QueryError::Other(e) - })?; - - let signers = self - .attestation_signers - .value_immediate() - .ok_or_else(|| QueryError::Other(anyhow::anyhow!("System is not ready yet")))?; - let signer = signers.get(&allocation_id).ok_or_else(|| { - let err_msg = format!("No signer found for allocation id {}", allocation_id); - IndexerError::new( - IndexerErrorCode::IE022, - Some(IndexerErrorCause::new(err_msg.clone())), - ); - - QueryError::Other(anyhow::anyhow!(err_msg)) - })?; - - let response = self - .graph_node - .subgraph_query_raw(&subgraph_deployment_id, query.clone()) - .await?; - - let attestation = response - .attestable - .then(|| Self::create_attestation(signer, &query, &response)); - - Ok(Response { - result: QueryResult { - graphql_response: response.graphql_response, - attestation, - }, - status: 200, - }) - } - - fn create_attestation( - signer: &AttestationSigner, - query: &str, - response: &UnattestedQueryResult, - ) -> Attestation { - signer.create_attestation(query, &response.graphql_response) - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use alloy_primitives::Address; - use ethers_core::types::U256; - use indexer_common::prelude::{ - Allocation, AllocationStatus, AttestationSigner, SubgraphDeployment, - }; - use lazy_static::lazy_static; - - use super::*; - - const INDEXER_OPERATOR_MNEMONIC: &str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; - const INDEXER_ADDRESS: &str = "0x1234567890123456789012345678901234567890"; - - lazy_static! { - static ref DEPLOYMENT_ID: DeploymentId = DeploymentId( - "0xc064c354bc21dd958b1d41b67b8ef161b75d2246b425f68ed4c74964ae705cbd" - .parse() - .unwrap(), - ); - } - - #[test] - fn paid_query_attestation() { - let subgraph_deployment = SubgraphDeployment { - id: *DEPLOYMENT_ID, - denied_at: None, - }; - - let indexer = Address::from_str(INDEXER_ADDRESS).unwrap(); - let allocation = &Allocation { - id: Address::from_str("0x4CAF2827961262ADEF3D0Ad15C341e40c21389a4").unwrap(), - status: AllocationStatus::Null, - subgraph_deployment, - indexer, - allocated_tokens: U256::from(100), - created_at_epoch: 940, - created_at_block_hash: String::from(""), - closed_at_epoch: None, - closed_at_epoch_start_block_hash: None, - previous_epoch_start_block_hash: None, - poi: None, - query_fee_rebates: None, - query_fees_collected: None, - }; - - let attestation_signer = AttestationSigner::new( - INDEXER_OPERATOR_MNEMONIC, - allocation, - U256::from(1), - Address::from_str("0xdeadbeefcafebabedeadbeefcafebabedeadbeef").unwrap(), - ) - .unwrap(); - - let request = "test input"; - let response = "test output"; - let attestation = QueryProcessor::create_attestation( - &attestation_signer, - request, - &UnattestedQueryResult { - graphql_response: response.to_owned(), - attestable: true, - }, - ); - - attestation_signer - .verify(&attestation, request, response, &allocation.id) - .unwrap(); - } -} diff --git a/service/src/server/routes/cost.rs b/service/src/routes/cost.rs similarity index 64% rename from service/src/server/routes/cost.rs rename to service/src/routes/cost.rs index caeb39ad3..0c9612b2e 100644 --- a/service/src/server/routes/cost.rs +++ b/service/src/routes/cost.rs @@ -1,19 +1,15 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - use std::str::FromStr; +use std::sync::Arc; use async_graphql::{Context, EmptyMutation, EmptySubscription, Object, Schema, SimpleObject}; use async_graphql_axum::{GraphQLRequest, GraphQLResponse}; -use axum::extract::Extension; +use axum::extract::State; use serde::{Deserialize, Serialize}; use serde_json::Value; use toolshed::thegraph::DeploymentId; -use crate::{ - common::indexer_management::{self, CostModel}, - server::ServerOptions, -}; +use crate::database::{self, CostModel}; +use crate::SubgraphServiceState; #[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)] pub struct GraphQlCostModel { @@ -32,13 +28,11 @@ impl From for GraphQlCostModel { } } -pub type CostSchema = Schema; - #[derive(Default)] -pub struct QueryRoot; +pub struct Query; #[Object] -impl QueryRoot { +impl Query { async fn cost_models( &self, ctx: &Context<'_>, @@ -48,8 +42,8 @@ impl QueryRoot { .into_iter() .map(|s| DeploymentId::from_str(&s)) .collect::, _>>()?; - let pool = &ctx.data_unchecked::().indexer_management_db; - let cost_models = indexer_management::cost_models(pool, &deployment_ids).await?; + let pool = &ctx.data_unchecked::>().database; + let cost_models = database::cost_models(pool, &deployment_ids).await?; Ok(cost_models.into_iter().map(|m| m.into()).collect()) } @@ -59,20 +53,31 @@ impl QueryRoot { deployment: String, ) -> Result, anyhow::Error> { let deployment_id = DeploymentId::from_str(&deployment)?; - let pool = &ctx.data_unchecked::().indexer_management_db; - indexer_management::cost_model(pool, &deployment_id) + let pool = &ctx.data_unchecked::>().database; + database::cost_model(pool, &deployment_id) .await .map(|model_opt| model_opt.map(GraphQlCostModel::from)) } } -pub(crate) async fn graphql_handler( +pub type CostSchema = Schema; + +pub async fn build_schema() -> CostSchema { + Schema::build( + Query::default(), + EmptyMutation::default(), + EmptySubscription::default(), + ) + .finish() +} + +pub async fn cost( + State(state): State>, req: GraphQLRequest, - Extension(schema): Extension, - Extension(server_options): Extension, ) -> GraphQLResponse { - schema - .execute(req.into_inner().data(server_options)) + state + .cost_schema + .execute(req.into_inner().data(state.clone())) .await .into() } diff --git a/service/src/routes/mod.rs b/service/src/routes/mod.rs new file mode 100644 index 000000000..4953d4c01 --- /dev/null +++ b/service/src/routes/mod.rs @@ -0,0 +1,4 @@ +pub mod cost; +mod status; + +pub use status::status; diff --git a/service/src/routes/status.rs b/service/src/routes/status.rs new file mode 100644 index 000000000..0a5ab27b6 --- /dev/null +++ b/service/src/routes/status.rs @@ -0,0 +1,114 @@ +// Copyright 2023-, GraphOps and Semiotic Labs. +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::HashSet; +use std::sync::Arc; + +use async_graphql_axum::GraphQLRequest; +use axum::{extract::State, response::IntoResponse, Json}; +use graphql::graphql_parser::query as q; +use graphql_http::{ + http::request::{IntoRequestParameters, RequestParameters}, + http_client::{ReqwestExt, ResponseError}, +}; +use serde_json::{json, Map, Value}; + +use crate::{SubgraphServiceError, SubgraphServiceState}; + +lazy_static::lazy_static! { + static ref SUPPORTED_ROOT_FIELDS: HashSet<&'static str> = + vec![ + "indexingStatuses", + "chains", + "latestBlock", + "earliestBlock", + "publicProofsOfIndexing", + "entityChangesInBlock", + "blockData", + "cachedEthereumCalls", + "subgraphFeatures", + "apiVersions", + ].into_iter().collect(); +} + +struct WrappedGraphQLRequest(async_graphql::Request); + +impl IntoRequestParameters for WrappedGraphQLRequest { + fn into_request_parameters(self) -> RequestParameters { + RequestParameters { + query: self.0.query.into(), + operation_name: self.0.operation_name, + variables: Map::from_iter(self.0.variables.iter().map(|(name, value)| { + ( + name.as_str().to_string(), + value.clone().into_json().unwrap(), + ) + })), + extensions: Map::from_iter(self.0.extensions.into_iter().map(|(name, value)| { + ( + name.as_str().to_string(), + value.clone().into_json().unwrap(), + ) + })), + } + } +} + +// Custom middleware function to process the request before reaching the main handler +pub async fn status( + State(state): State>, + request: GraphQLRequest, +) -> Result { + let request = request.into_inner(); + let query: q::Document = q::parse_query(request.query.as_str()) + .map_err(|e| SubgraphServiceError::InvalidStatusQuery(e.into()))?; + + let root_fields = query + .definitions + .iter() + // This gives us all root selection sets + .filter_map(|def| match def { + q::Definition::Operation(op) => match op { + q::OperationDefinition::Query(query) => Some(&query.selection_set), + q::OperationDefinition::SelectionSet(selection_set) => Some(&selection_set), + _ => None, + }, + q::Definition::Fragment(fragment) => Some(&fragment.selection_set), + }) + // This gives us all field names of root selection sets (and potentially non-root fragments) + .flat_map(|selection_set| { + selection_set + .items + .iter() + .filter_map(|item| match item { + q::Selection::Field(field) => Some(&field.name), + _ => None, + }) + .collect::>() + }); + + let unsupported_root_fields: Vec<_> = root_fields + .filter(|field| !SUPPORTED_ROOT_FIELDS.contains(field.as_str())) + .map(ToString::to_string) + .collect(); + + if !unsupported_root_fields.is_empty() { + return Err(SubgraphServiceError::UnsupportedStatusQueryFields( + unsupported_root_fields, + )); + } + + let result = state + .graph_node_client + .post(&state.graph_node_status_url) + .send_graphql::(WrappedGraphQLRequest(request)) + .await + .map_err(|e| SubgraphServiceError::StatusQueryError(e.into()))?; + + result.map(Json).or_else(|e| match e { + ResponseError::Failure { errors } => Ok(Json(json!({ + "errors": errors, + }))), + ResponseError::Empty => todo!(), + }) +} diff --git a/service/src/server/mod.rs b/service/src/server/mod.rs deleted file mode 100644 index 329f2cc34..000000000 --- a/service/src/server/mod.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -pub(crate) use axum::{ - error_handling::HandleErrorLayer, - handler::Handler, - http::{Method, StatusCode}, - routing::get, -}; - -use axum::{routing::post, Extension, Router}; -use sqlx::PgPool; -use std::time::Duration; -use tower::{BoxError, ServiceBuilder}; -use tower_http::{ - add_extension::AddExtensionLayer, - cors::CorsLayer, - trace::{self, TraceLayer}, -}; -use tracing::Level; - -use indexer_common::{indexer_service::http::IndexerServiceRelease, prelude::SubgraphClient}; - -use crate::{ - query_processor::QueryProcessor, - server::routes::{network_ratelimiter, slow_ratelimiter}, -}; - -pub mod routes; - -#[derive(Clone)] -pub struct ServerOptions { - pub port: Option, - pub release: IndexerServiceRelease, - pub query_processor: QueryProcessor, - pub free_query_auth_token: Option, - pub graph_node_status_endpoint: String, - pub indexer_management_db: PgPool, - pub operator_public_key: String, - pub network_subgraph: &'static SubgraphClient, - pub network_subgraph_auth_token: Option, - pub serve_network_subgraph: bool, -} - -impl ServerOptions { - #[allow(clippy::too_many_arguments)] - pub fn new( - port: Option, - release: IndexerServiceRelease, - query_processor: QueryProcessor, - free_query_auth_token: Option, - graph_node_status_endpoint: String, - indexer_management_db: PgPool, - operator_public_key: String, - network_subgraph: &'static SubgraphClient, - network_subgraph_auth_token: Option, - serve_network_subgraph: bool, - ) -> Self { - let free_query_auth_token = free_query_auth_token.map(|token| format!("Bearer {}", token)); - - ServerOptions { - port, - release, - query_processor, - free_query_auth_token, - graph_node_status_endpoint, - indexer_management_db, - operator_public_key, - network_subgraph, - network_subgraph_auth_token, - serve_network_subgraph, - } - } -} - -pub async fn create_server(options: ServerOptions) -> Router { - Router::new() - .route("/", get(routes::basic::index)) - .route("/health", get(routes::basic::health)) - .route("/version", get(routes::basic::version)) - .route( - "/status", - post(routes::status::status_queries) - .layer(AddExtensionLayer::new(network_ratelimiter())), - ) - .route( - "/subgraphs/health/:deployment", - get(routes::deployment::deployment_health - .layer(AddExtensionLayer::new(slow_ratelimiter()))), - ) - .route( - "/cost", - post(routes::cost::graphql_handler) - .get(routes::cost::graphql_handler) - .layer(AddExtensionLayer::new(slow_ratelimiter())), - ) - .nest( - "/operator", - routes::basic::create_operator_server(options.clone()) - .layer(AddExtensionLayer::new(slow_ratelimiter())), - ) - .route( - "/network", - post(routes::network::network_queries) - .layer(AddExtensionLayer::new(network_ratelimiter())), - ) - .route( - "/subgraphs/id/:id", - post(routes::subgraphs::subgraph_queries), - ) - .layer(Extension(options.clone())) - .layer(CorsLayer::new().allow_methods([Method::GET, Method::POST])) - .layer( - // Handle error for timeout, ratelimit, or a general internal server error - ServiceBuilder::new() - .layer(HandleErrorLayer::new(|error: BoxError| async move { - if error.is::() { - Ok(StatusCode::REQUEST_TIMEOUT) - } else { - Err(( - StatusCode::INTERNAL_SERVER_ERROR, - format!("Unhandled internal error: {}", error), - )) - } - })) - .layer( - TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new().level(Level::DEBUG)) - .on_response(trace::DefaultOnResponse::new().level(Level::DEBUG)), - ) - .timeout(Duration::from_secs(10)) - .into_inner(), - ) -} diff --git a/service/src/server/routes/basic.rs b/service/src/server/routes/basic.rs deleted file mode 100644 index 1c0f2f8aa..000000000 --- a/service/src/server/routes/basic.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use axum::{extract::Extension, routing::get, Router}; -use axum::{http::StatusCode, response::IntoResponse, Json}; -use serde::Serialize; -use serde_json::json; - -use crate::server::ServerOptions; - -#[derive(Serialize)] -struct Health { - healthy: bool, -} - -/// Endpoint for server health -pub async fn health() -> impl IntoResponse { - let health = Health { healthy: true }; - (StatusCode::OK, Json(health)) -} - -/// Index endpoint for status checks -pub async fn index() -> impl IntoResponse { - let responder = "Ready to roll!".to_string(); - responder.into_response() -} - -/// Endpoint for package version -pub async fn version(server: axum::extract::Extension) -> impl IntoResponse { - let version = server.release.clone(); - (StatusCode::OK, Json(version)) -} - -// Define a handler function for the `/info` route -async fn operator_info(Extension(options): Extension) -> Json { - let public_key = &options.operator_public_key; - Json(json!({ "publicKey": public_key })) -} - -// Create a function to build the operator server router -pub fn create_operator_server(_options: ServerOptions) -> Router { - Router::new().route("/info", get(operator_info)) -} diff --git a/service/src/server/routes/deployment.rs b/service/src/server/routes/deployment.rs deleted file mode 100644 index 855190890..000000000 --- a/service/src/server/routes/deployment.rs +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use axum::{http::StatusCode, response::IntoResponse, Extension, Json}; - -use serde::{Deserialize, Serialize}; -use serde_json::json; - -use crate::server::{routes::internal_server_error_response, ServerOptions}; -use indexer_common::indexer_errors::{IndexerError, IndexerErrorCause}; - -/// Parse an incoming query request and route queries with authenticated -/// free query token to graph node -/// Later add receipt manager functions for paid queries -pub async fn deployment_health( - Extension(server): Extension, - deployment: axum::extract::Path, -) -> impl IntoResponse { - // Create the GraphQL query - let query = status_query(deployment.to_string()); - - // Send the GraphQL request - let response = reqwest::Client::new() - .post(server.graph_node_status_endpoint) - .header("Content-Type", "application/json") - .json(&query) - .send() - .await; - - match response { - Ok(response) => { - if response.status().is_success() { - // Deserialize the JSON response - //TODO: match with error - let data: serde_json::Value = if let Ok(data) = response.json().await { - data - } else { - return internal_server_error_response("Invalid json response"); - }; - - // Process the response and return the appropriate HTTP status - let status = if let Some(status) = - data["data"]["indexingStatuses"].get(0).and_then(|s| { - let parse = serde_json::from_value::(s.clone()); - parse.ok() - }) { - status - } else { - return internal_server_error_response("Missing indexing status"); - }; - - // Build health response based on the returned status - if status.health == SubgraphHealth::failed { - return internal_server_error_response("Subgraph deployment has failed"); - } - - if let Ok((latest, head)) = block_numbers(status) { - if latest > head - 5 { - (StatusCode::OK, Json("Subgraph deployment is up to date")).into_response() - } else { - internal_server_error_response("Subgraph deployment is lagging behind") - } - } else { - internal_server_error_response( - "Invalid indexing status (missing block numbers)", - ) - } - } else { - internal_server_error_response("Unknown error") - } - } - Err(e) => internal_server_error_response(&e.to_string()), - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -struct IndexingStatus { - health: SubgraphHealth, - chains: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[allow(non_camel_case_types)] // Need exact field names to match with GQL response -enum SubgraphHealth { - healthy, - unhealthy, - failed, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ChainStatus { - network: String, - latest_block: Block, - chain_head_block: Block, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -struct Block { - number: String, - hash: String, -} - -fn status_query(deployment: String) -> serde_json::Value { - json!({ - "query": r#"query indexingStatus($subgraphs: [String!]!) { - indexingStatuses(subgraphs: $subgraphs) { - subgraph - health - chains { - network - ... on EthereumIndexingStatus { - latestBlock { number hash } - chainHeadBlock { number hash } - } - } - } - }"#, - "variables": { - "subgraphs": [deployment], - }, - }) -} - -fn block_numbers(status: IndexingStatus) -> Result<(u64, u64), IndexerError> { - let latest_block_number = status - .chains - .get(0) - .map(|chain| chain.latest_block.number.clone()) - .map(|number| number.parse::()); - - let head_block_number = status - .chains - .get(0) - .map(|chain| chain.chain_head_block.number.clone()) - .map(|number| number.parse::()); - - if let (Some(Ok(latest)), Some(Ok(head))) = (latest_block_number, head_block_number) { - Ok((latest, head)) - } else { - Err(IndexerError::new( - indexer_common::indexer_errors::IndexerErrorCode::IE018, - Some(IndexerErrorCause::new( - "Ill formatted block numbers from indexing status", - )), - )) - } -} diff --git a/service/src/server/routes/mod.rs b/service/src/server/routes/mod.rs deleted file mode 100644 index f0aae9888..000000000 --- a/service/src/server/routes/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use axum::{ - http::StatusCode, - response::{IntoResponse, Response}, - Json, -}; -use hyper::http::HeaderName; -use indexer_common::indexer_errors::{IndexerError, IndexerErrorCause}; -use tower::limit::RateLimitLayer; - -pub mod basic; -pub mod cost; -pub mod deployment; -pub mod network; -pub mod status; -pub mod subgraphs; - -/// Helper function to convert response body to query string -pub async fn response_body_to_query_string( - body: hyper::body::Body, -) -> Result { - let query_bytes = hyper::body::to_bytes(body).await.map_err(|e| { - IndexerError::new( - indexer_common::indexer_errors::IndexerErrorCode::IE075, - Some(IndexerErrorCause::new(e)), - ) - })?; - let query_string = String::from_utf8(query_bytes.to_vec()).map_err(|e| { - IndexerError::new( - indexer_common::indexer_errors::IndexerErrorCode::IE075, - Some(IndexerErrorCause::new(e)), - ) - })?; - Ok(query_string) -} - -/// Create response for a bad request -pub fn bad_request_response(error_body: &str) -> Response { - ( - StatusCode::BAD_REQUEST, - axum::response::AppendHeaders([(HeaderName::from_static("graph-attestable"), "false")]), - Json(error_body.to_string()), - ) - .into_response() -} - -/// Create response for an internal server error -pub fn internal_server_error_response(error_body: &str) -> Response { - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(error_body.to_string()), - ) - .into_response() -} - -/// Limit status requests to 9000/30min (5/s) -pub fn slow_ratelimiter() -> RateLimitLayer { - RateLimitLayer::new(9000, std::time::Duration::from_millis(30 * 60 * 1000)) -} - -/// Limit network requests to 90000/30min (50/s) -pub fn network_ratelimiter() -> RateLimitLayer { - RateLimitLayer::new(90000, std::time::Duration::from_millis(30 * 60 * 1000)) -} diff --git a/service/src/server/routes/network.rs b/service/src/server/routes/network.rs deleted file mode 100644 index ce330c932..000000000 --- a/service/src/server/routes/network.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use axum::{ - extract::Extension, - http::{self, Request}, - response::IntoResponse, - Json, -}; -use serde_json::{json, Value}; - -use crate::server::ServerOptions; - -use super::bad_request_response; - -pub async fn network_queries( - Extension(server): Extension, - req: Request, - axum::extract::Json(body): axum::extract::Json, -) -> impl IntoResponse { - // Extract free query auth token - let auth_token = req - .headers() - .get(http::header::AUTHORIZATION) - .and_then(|t| t.to_str().ok()); - - // Serve only if enabled by indexer and request auth token matches - if !(server.serve_network_subgraph - && auth_token.is_some() - && server.network_subgraph_auth_token.is_some() - && auth_token.unwrap() == server.network_subgraph_auth_token.as_deref().unwrap()) - { - return bad_request_response("Not enabled or authorized query"); - } - - match server.network_subgraph.query::(&body).await { - Ok(result) => Json(json!({ - "data": result.data, - "errors": result.errors.map(|errors| { - errors - .into_iter() - .map(|e| json!({ "message": e.message })) - .collect::>() - }), - })) - .into_response(), - Err(e) => bad_request_response(&e.to_string()), - } -} diff --git a/service/src/server/routes/status.rs b/service/src/server/routes/status.rs deleted file mode 100644 index 630411eb3..000000000 --- a/service/src/server/routes/status.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use std::collections::HashSet; - -use axum::{ - http::{Request, StatusCode}, - response::IntoResponse, - Extension, Json, -}; - -use hyper::body::Bytes; - -use reqwest::{header, Client}; - -use crate::server::ServerOptions; -use indexer_common::{graphql::filter_supported_fields, indexer_errors::*}; - -use super::bad_request_response; - -lazy_static::lazy_static! { - static ref SUPPORTED_ROOT_FIELDS: HashSet<&'static str> = - vec![ - "indexingStatuses", - "chains", - "latestBlock", - "earliestBlock", - "publicProofsOfIndexing", - "entityChangesInBlock", - "blockData", - "cachedEthereumCalls", - "subgraphFeatures", - "apiVersions", - ].into_iter().collect(); -} - -// Custom middleware function to process the request before reaching the main handler -pub async fn status_queries( - Extension(server): Extension, - req: Request, -) -> impl IntoResponse { - let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap(); - // Read the requested query string - let query_string = match String::from_utf8(body_bytes.to_vec()) { - Ok(s) => s, - Err(e) => return bad_request_response(&e.to_string()), - }; - - // filter supported root fields - let query_string = match filter_supported_fields(&query_string, &SUPPORTED_ROOT_FIELDS) { - Ok(query) => query, - Err(unsupported_fields) => { - return ( - StatusCode::BAD_REQUEST, - format!("Cannot query field: {:#?}", unsupported_fields), - ) - .into_response(); - } - }; - - // Pass the modified operation to the actual endpoint - let request = Client::new() - .post(&server.graph_node_status_endpoint) - .body(Bytes::from(query_string)) - .header(header::CONTENT_TYPE, "application/json"); - - match request.send().await { - Ok(r) => match r.json::>().await { - Ok(r) => (StatusCode::OK, Json(r)).into_response(), - Err(e) => { - IndexerError::new( - IndexerErrorCode::IE018, - Some(IndexerErrorCause::new( - "Failed to parse the indexing status API response", - )), - ); - bad_request_response(&e.to_string()) - } - }, - Err(e) => { - IndexerError::new( - IndexerErrorCode::IE018, - Some(IndexerErrorCause::new( - "Failed to query indexing status API from the graph node status endpoint", - )), - ); - bad_request_response(&e.to_string()) - } - } -} diff --git a/service/src/server/routes/subgraphs.rs b/service/src/server/routes/subgraphs.rs deleted file mode 100644 index ec471964c..000000000 --- a/service/src/server/routes/subgraphs.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use axum::{ - extract::Extension, - http::{self, Request, StatusCode}, - response::IntoResponse, - Json, -}; -use std::str::FromStr; -use toolshed::thegraph::DeploymentId; -use tracing::trace; - -use crate::{ - metrics, - query_processor::FreeQuery, - server::{ - routes::{bad_request_response, response_body_to_query_string}, - ServerOptions, - }, -}; -use indexer_common::indexer_errors::*; - -/// Parse an incoming query request and route queries with authenticated -/// free query token to graph node -/// Later add receipt manager functions for paid queries -pub async fn subgraph_queries( - Extension(server): Extension, - id: axum::extract::Path, - req: Request, -) -> impl IntoResponse { - let (parts, body) = req.into_parts(); - - // Initialize id into a subgraph deployment ID - let subgraph_deployment_id = match DeploymentId::from_str(id.as_str()) { - Ok(id) => id, - Err(e) => return bad_request_response(&e.to_string()), - }; - let deployment_label = subgraph_deployment_id.to_string(); - - let query_duration_timer = metrics::QUERY_DURATION - .with_label_values(&[&deployment_label]) - .start_timer(); - metrics::QUERIES - .with_label_values(&[&deployment_label]) - .inc(); - // Extract scalar receipt from header and free query auth token for paid or free query - let receipt = if let Some(receipt) = parts.headers.get("scalar-receipt") { - match receipt.to_str() { - Ok(r) => Some(r), - Err(_) => { - query_duration_timer.observe_duration(); - metrics::QUERIES_WITH_INVALID_RECEIPT_HEADER - .with_label_values(&[&deployment_label]) - .inc(); - let err_msg = "Bad scalar receipt for subgraph query"; - IndexerError::new( - IndexerErrorCode::IE029, - Some(IndexerErrorCause::new(err_msg)), - ); - return bad_request_response(err_msg); - } - } - } else { - None - }; - trace!( - "receipt attached by the query, can pass it to TAP: {:?}", - receipt - ); - - // Extract free query auth token - let auth_token = parts - .headers - .get(http::header::AUTHORIZATION) - .and_then(|t| t.to_str().ok()); - // determine if the query is paid or authenticated to be free - let free = auth_token.is_some() - && server.free_query_auth_token.is_some() - && auth_token.unwrap() == server.free_query_auth_token.as_deref().unwrap(); - - let query_string = match response_body_to_query_string(body).await { - Ok(q) => q, - Err(e) => { - query_duration_timer.observe_duration(); - return bad_request_response(&e.to_string()); - } - }; - - if free { - let free_query = FreeQuery { - subgraph_deployment_id, - query: query_string, - }; - - match server.query_processor.execute_free_query(free_query).await { - Ok(res) if res.status == 200 => { - query_duration_timer.observe_duration(); - (StatusCode::OK, Json(res.result)).into_response() - } - _ => { - IndexerError::new( - IndexerErrorCode::IE033, - Some(IndexerErrorCause::new( - "Failed to execute a free subgraph query to graph node", - )), - ); - bad_request_response("Failed to execute free query") - } - } - } else if let Some(receipt) = receipt { - let paid_query = crate::query_processor::PaidQuery { - subgraph_deployment_id, - query: query_string, - receipt: receipt.to_string(), - }; - - match server.query_processor.execute_paid_query(paid_query).await { - Ok(res) => { - query_duration_timer.observe_duration(); - metrics::SUCCESSFUL_QUERIES - .with_label_values(&[&deployment_label]) - .inc(); - (StatusCode::OK, Json(res.result)).into_response() - } - Err(e) => { - metrics::FAILED_QUERIES - .with_label_values(&[&deployment_label]) - .inc(); - let err_msg = format!( - "Failed to execute a paid subgraph query to graph node: {}", - e - ); - IndexerError::new(IndexerErrorCode::IE032, Some(IndexerErrorCause::new(e))); - return bad_request_response(&err_msg); - } - } - } else { - let error_body = "Query request header missing scalar-receipts or incorrect auth token"; - metrics::QUERIES_WITHOUT_RECEIPT - .with_label_values(&[&deployment_label]) - .inc(); - IndexerError::new( - IndexerErrorCode::IE030, - Some(IndexerErrorCause::new(error_body)), - ); - query_duration_timer.observe_duration(); - bad_request_response(error_body) - } -} diff --git a/service/src/test_vectors.rs b/service/src/test_vectors.rs deleted file mode 100644 index b21c78e71..000000000 --- a/service/src/test_vectors.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use std::str::FromStr; - -use alloy_primitives::Address; -use lazy_static::lazy_static; - -lazy_static! { - pub static ref INDEXER_ADDRESS: Address = - Address::from_str("0x1234567890123456789012345678901234567890").unwrap(); -} diff --git a/service/src/util.rs b/service/src/util.rs deleted file mode 100644 index 0c64abc68..000000000 --- a/service/src/util.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2023-, GraphOps and Semiotic Labs. -// SPDX-License-Identifier: Apache-2.0 - -use ethers::signers::WalletError; -use tokio::signal; -use tracing::{ - info, - subscriber::{set_global_default, SetGlobalDefaultError}, -}; -use tracing_subscriber::{EnvFilter, FmtSubscriber}; - -use crate::common::address::{build_wallet, wallet_address}; - -/// Validate that private key as an Eth wallet -pub fn public_key(value: &str) -> Result { - // The wallet can be stored instead of the original private key - let wallet = build_wallet(value)?; - let addr = wallet_address(&wallet); - info!(address = addr, "Resolved Graphcast id"); - Ok(addr) -} - -/// Sets up tracing, allows log level to be set from the environment variables -pub fn init_tracing(format: String) -> Result<(), SetGlobalDefaultError> { - let filter = EnvFilter::from_default_env(); - - let subscriber_builder: tracing_subscriber::fmt::SubscriberBuilder< - tracing_subscriber::fmt::format::DefaultFields, - tracing_subscriber::fmt::format::Format, - EnvFilter, - > = FmtSubscriber::builder().with_env_filter(filter); - - match format.as_str() { - "json" => set_global_default(subscriber_builder.json().finish()), - "full" => set_global_default(subscriber_builder.finish()), - "compact" => set_global_default(subscriber_builder.compact().finish()), - _ => set_global_default(subscriber_builder.with_ansi(true).pretty().finish()), - } -} - -pub async fn shutdown_signal() { - let ctrl_c = async { - signal::ctrl_c() - .await - .expect("failed to install Ctrl+C handler"); - }; - - let terminate = async { - signal::unix::signal(signal::unix::SignalKind::terminate()) - .expect("failed to install signal handler") - .recv() - .await; - }; - - tokio::select! { - _ = ctrl_c => {}, - _ = terminate => {}, - } - - info!("signal received, starting graceful shutdown"); -}