Skip to content

Commit 6dfd9ab

Browse files
committed
feat: add /blocklist route (#991)
Resolves #990
1 parent 81b006b commit 6dfd9ab

File tree

5 files changed

+46
-66
lines changed

5 files changed

+46
-66
lines changed

src/config.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@ use anyhow::Context;
1010
use ipnetwork::IpNetwork;
1111
use ordered_float::NotNan;
1212
use semver::Version;
13-
use serde::Deserialize;
13+
use serde::{Deserialize, Serialize};
1414
use serde_with::{serde_as, DisplayFromStr};
15-
use thegraph_core::{Address, DeploymentId};
15+
use thegraph_core::{Address, BlockNumber, DeploymentId};
1616
use url::Url;
1717

18-
use crate::{
19-
auth::APIKey, indexers::public_poi::ProofOfIndexingInfo,
20-
network::subgraph_client::TrustedIndexer,
21-
};
18+
use crate::{auth::APIKey, network::subgraph_client::TrustedIndexer};
2219

2320
/// The Graph Gateway configuration.
2421
#[serde_as]
@@ -56,7 +53,7 @@ pub struct Config {
5653
pub payment_required: bool,
5754
/// POI blocklist
5855
#[serde(default)]
59-
pub poi_blocklist: Vec<ProofOfIndexingInfo>,
56+
pub poi_blocklist: Vec<BlockedPoi>,
6057
/// public API port
6158
pub port_api: u16,
6259
/// private metrics port
@@ -174,6 +171,17 @@ pub struct Receipts {
174171
pub verifier: Address,
175172
}
176173

174+
#[derive(Debug, Clone, Deserialize, Serialize)]
175+
pub struct BlockedPoi {
176+
pub public_poi: B256,
177+
pub deployment: DeploymentId,
178+
pub block_number: BlockNumber,
179+
/// Example query (should be minimal to reproduce bad response)
180+
pub query: Option<String>,
181+
/// Bad query response, from the above query executed on indexers with this blocked PoI
182+
pub bad_query_response: Option<String>,
183+
}
184+
177185
/// Load the configuration from a JSON file.
178186
pub fn load_from_file(path: &Path) -> anyhow::Result<Config> {
179187
let config_content = std::fs::read_to_string(path)?;

src/indexers/public_poi.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,6 @@ pub enum Error {
3535
EmptyResponse,
3636
}
3737

38-
#[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize)]
39-
pub struct ProofOfIndexingInfo {
40-
/// Proof of indexing (POI).
41-
pub proof_of_indexing: ProofOfIndexing,
42-
/// POI deployment ID (the IPFS Hash in the Graph Network Subgraph).
43-
pub deployment_id: DeploymentId,
44-
/// POI block number.
45-
pub block_number: BlockNumber,
46-
}
47-
48-
impl ProofOfIndexingInfo {
49-
/// Get the POI metadata.
50-
pub fn meta(&self) -> (DeploymentId, BlockNumber) {
51-
(self.deployment_id, self.block_number)
52-
}
53-
}
54-
55-
impl From<((DeploymentId, BlockNumber), ProofOfIndexing)> for ProofOfIndexingInfo {
56-
fn from(value: ((DeploymentId, BlockNumber), ProofOfIndexing)) -> Self {
57-
let ((deployment_id, block_number), proof_of_indexing) = value;
58-
Self {
59-
deployment_id,
60-
block_number,
61-
proof_of_indexing,
62-
}
63-
}
64-
}
65-
6638
#[derive(Clone, Debug, Serialize)]
6739
#[serde(rename_all = "camelCase")]
6840
struct PublicProofOfIndexingRequest {

src/main.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ async fn main() {
120120
conf.min_graph_node_version,
121121
conf.blocked_indexers,
122122
indexer_host_blocklist,
123-
conf.poi_blocklist,
123+
conf.poi_blocklist.clone(),
124124
);
125125
let indexing_perf = IndexingPerformance::new(network.clone());
126126
network.wait_until_ready().await;
@@ -172,6 +172,8 @@ async fn main() {
172172
reporter,
173173
};
174174

175+
let poi_blocklist: &'static str = serde_json::to_string(&conf.poi_blocklist).unwrap().leak();
176+
175177
// Host metrics on a separate server with a port that isn't open to public requests.
176178
tokio::spawn(async move {
177179
let router = Router::new().route("/metrics", routing::get(handle_metrics));
@@ -252,6 +254,13 @@ async fn main() {
252254
"/voucher",
253255
routing::post(vouchers::handle_voucher).with_state(legacy_signer),
254256
)
257+
.route(
258+
"/blocklist",
259+
routing::get(move || async move {
260+
let headers = [(reqwest::header::CONTENT_TYPE, "application/json")];
261+
(headers, poi_blocklist)
262+
}),
263+
)
255264
.nest("/api", api);
256265

257266
let app_listener = TcpListener::bind(SocketAddr::new(

src/network/indexer_indexing_poi_blocklist.rs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,25 @@ use std::collections::{HashMap, HashSet};
1111

1212
use thegraph_core::{BlockNumber, DeploymentId, ProofOfIndexing};
1313

14-
use crate::indexers::public_poi::ProofOfIndexingInfo;
14+
use crate::config::BlockedPoi;
1515

1616
/// A blocklist based on the Proof of Indexing (POI) of indexers.
1717
#[derive(Default)]
1818
pub struct PoiBlocklist {
19-
blocklist: HashMap<DeploymentId, HashSet<ProofOfIndexingInfo>>,
19+
blocklist: HashMap<DeploymentId, Vec<(BlockNumber, ProofOfIndexing)>>,
2020
}
2121

2222
impl PoiBlocklist {
23-
pub fn new(conf: Vec<ProofOfIndexingInfo>) -> Self {
24-
// Group the blocked POI info by deployment ID
25-
let mut conf_map = HashMap::new();
23+
pub fn new(conf: Vec<BlockedPoi>) -> Self {
24+
let mut blocklist: HashMap<DeploymentId, Vec<(BlockNumber, ProofOfIndexing)>> =
25+
Default::default();
2626
for info in conf.into_iter() {
27-
conf_map
28-
.entry(info.deployment_id)
29-
.or_insert_with(HashSet::new)
30-
.insert(info);
31-
}
32-
33-
Self {
34-
blocklist: conf_map,
27+
blocklist
28+
.entry(info.deployment)
29+
.or_default()
30+
.push((info.block_number, info.public_poi.into()));
3531
}
32+
Self { blocklist }
3633
}
3734

3835
pub fn is_empty(&self) -> bool {
@@ -49,11 +46,11 @@ impl PoiBlocklist {
4946
) -> Vec<(DeploymentId, BlockNumber)> {
5047
deployments
5148
.into_iter()
52-
.flat_map(|deployment_id| {
53-
self.blocklist
54-
.get(deployment_id)
55-
.into_iter()
56-
.flat_map(|pois| pois.iter().map(|poi_info| poi_info.meta()))
49+
.flat_map(|deployment| {
50+
self.blocklist.get(deployment).into_iter().flat_map(|pois| {
51+
pois.iter()
52+
.map(|(block_number, _)| (*deployment, *block_number))
53+
})
5754
})
5855
.collect()
5956
}
@@ -74,17 +71,13 @@ impl PoiBlocklist {
7471
/// Check if the POI is in the blocklist.
7572
fn check_poi(
7673
&self,
77-
deployment_id: DeploymentId,
74+
deployment: DeploymentId,
7875
block_number: BlockNumber,
7976
poi: ProofOfIndexing,
8077
) -> bool {
81-
match self.blocklist.get(&deployment_id) {
78+
match self.blocklist.get(&deployment) {
8279
None => false,
83-
Some(blocked_pois) => blocked_pois.iter().any(|blocked| {
84-
blocked.deployment_id == deployment_id
85-
&& blocked.block_number == block_number
86-
&& blocked.proof_of_indexing == poi
87-
}),
80+
Some(blocked_pois) => blocked_pois.contains(&(block_number, poi)),
8881
}
8982
}
9083
}

src/network/service.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use super::{
2828
subgraph_client::Client as SubgraphClient,
2929
ResolutionError,
3030
};
31-
use crate::{config::BlockedIndexer, indexers::public_poi::ProofOfIndexingInfo};
31+
use crate::config::{BlockedIndexer, BlockedPoi};
3232

3333
/// Subgraph resolution information returned by the [`NetworkService`].
3434
pub struct ResolvedSubgraphInfo {
@@ -177,7 +177,7 @@ pub fn spawn(
177177
min_graph_node_version: Version,
178178
indexer_blocklist: BTreeMap<Address, BlockedIndexer>,
179179
indexer_host_blocklist: HashSet<IpNetwork>,
180-
indexer_pois_blocklist: Vec<ProofOfIndexingInfo>,
180+
poi_blocklist: Vec<BlockedPoi>,
181181
) -> NetworkService {
182182
let internal_state = InternalState {
183183
indexer_blocklist,
@@ -189,9 +189,7 @@ pub fn spawn(
189189
min_graph_node_version,
190190
},
191191
indexer_version_resolver: VersionResolver::new(http_client.clone(), Duration::from_secs(5)),
192-
poi_blocklist: PoiBlocklist::new(
193-
indexer_pois_blocklist.into_iter().map(Into::into).collect(),
194-
),
192+
poi_blocklist: PoiBlocklist::new(poi_blocklist),
195193
poi_resolver: PoiResolver::new(
196194
http_client.clone(),
197195
Duration::from_secs(5),

0 commit comments

Comments
 (0)