Skip to content

Commit 94b30d3

Browse files
committed
Reject requests for blocks before subgraph minimum
1 parent e9e6f1a commit 94b30d3

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,9 @@ async fn handle_subgraph_query_inner(
519519
QueryEngineError::FeesTooHigh(count) => {
520520
format!("No suitable indexer found, {} indexers requesting higher fees for this query", count)
521521
}
522+
QueryEngineError::BlockBeforeMin => {
523+
"Requested block before minimum `startBlock` of subgraph manifest".into()
524+
}
522525
QueryEngineError::MissingBlock(_) => {
523526
"Gateway failed to resolve required blocks".into()
524527
}

src/manifest_client.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub struct SubgraphInfo {
1111
pub deployment: SubgraphDeploymentID,
1212
pub network: String,
1313
pub features: Vec<String>,
14+
pub min_block: u64,
1415
}
1516

1617
pub type SubgraphInfoMap =
@@ -74,21 +75,31 @@ pub async fn fetch_manifest(
7475
.map_err(|err| (deployment, err.to_string()))?;
7576
let manifest = serde_yaml::from_str::<SubgraphManifest>(&payload)
7677
.map_err(|err| (deployment, err.to_string()))?;
78+
let min_block = manifest
79+
.data_sources
80+
.iter()
81+
.map(|data_source| data_source.source.start_block.unwrap_or(0))
82+
.min()
83+
.unwrap_or(0);
7784
// We are assuming that all `dataSource.network` fields are identical.
7885
// This is guaranteed for now.
7986
let network = manifest
8087
.data_sources
8188
.into_iter()
82-
.filter_map(|data_source| data_source.network)
89+
.map(|data_source| data_source.network)
8390
.next()
8491
.ok_or_else(|| (deployment, "Network not found".to_string()))?;
8592
Ok(SubgraphInfo {
8693
deployment,
8794
network,
95+
min_block,
8896
features: manifest.features,
8997
})
9098
}
9199

100+
// Subgraph manifest schema:
101+
// https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md
102+
92103
#[derive(Deserialize)]
93104
#[serde(rename_all = "camelCase")]
94105
pub struct SubgraphManifest {
@@ -98,6 +109,14 @@ pub struct SubgraphManifest {
98109
}
99110

100111
#[derive(Deserialize)]
112+
#[serde(rename_all = "camelCase")]
101113
pub struct DataSource {
102-
pub network: Option<String>,
114+
pub network: String,
115+
pub source: EthereumContractSource,
116+
}
117+
118+
#[derive(Deserialize)]
119+
#[serde(rename_all = "camelCase")]
120+
pub struct EthereumContractSource {
121+
pub start_block: Option<u64>,
103122
}

src/query_engine/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ pub enum QueryEngineError {
120120
NoIndexerSelected,
121121
FeesTooHigh(usize),
122122
MalformedQuery,
123+
BlockBeforeMin,
123124
MissingBlock(UnresolvedBlock),
124125
}
125126

@@ -276,6 +277,12 @@ where
276277
let freshness_requirements =
277278
Indexers::freshness_requirements(&mut context, block_resolver).await?;
278279

280+
// Reject queries for blocks before minimum start block of subgraph manifest.
281+
match freshness_requirements.minimum_block {
282+
Some(min_block) if min_block < subgraph.min_block => return Err(BlockBeforeMin),
283+
_ => (),
284+
};
285+
279286
for retry_count in 0..self.config.indexer_selection_retry_limit {
280287
let selection_timer = with_metric(
281288
&METRICS.indexer_selection_duration,

src/query_engine/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ impl Topology {
169169
query.subgraph = Some(Ptr::new(SubgraphInfo {
170170
deployment: deployment.id,
171171
network: deployment.network,
172+
min_block: 0,
172173
features: vec![],
173174
}));
174175
query

0 commit comments

Comments
 (0)