Skip to content

store: refuse a proof of indexing for a pruned block - #6754

Open
lx3133584 wants to merge 1 commit into
graphprotocol:masterfrom
lx3133584:pruned-poi-error
Open

lx3133584 wants to merge 1 commit into
graphprotocol:masterfrom
lx3133584:pruned-poi-error

Conversation

@lx3133584

Copy link
Copy Markdown

Fixes #6751

Problem

get_proof_of_indexing compared the requested block to the deployment's head, but never to earliest_block_number. A block below it has had its causality-region digests removed by pruning, so the query at that block returns an incomplete set. ProofOfIndexingFinisher hashes whatever it gets into a well-formed POI, and that value is returned as a normal result.

This is worse than an error: nothing downstream can tell the value is wrong. Pruned nodes agree with each other, so cross-checking between an operator's own nodes does not catch it either. It has already produced a disputed POI in production.

get_public_proof_of_indexing goes through the same function, so it had the same problem.

Fix

Refuse to compute a POI for a block below the earliest retained block, and say which block is still available.

The rest of the function is unchanged: a retained block behaves exactly as before, and a block above the head keeps its existing deterministic-failure handling.

Testing

Added store/test-store/tests/postgres/pruned_poi.rs, which creates a test subgraph, sets its head to 200 and its earliest_block_number to 100, then asks for a POI at 120 and at 50.

  • At 120 (retained) the call still returns Ok.
  • At 50 (pruned) the call must be an error mentioning the pruning.

Without the change, the second case returns a valid-looking 32-byte hash, so the test fails with that hash printed. With it, the call returns the "has been pruned" error.

$ cargo test -p test-store --test postgres
test result: ok. 99 passed; 0 failed

The test harness needs THEGRAPH_STORE_POSTGRES_DIESEL_URL pointed at a Postgres 14 instance created with --locale=C, as tests/docker-compose.yml describes.

Out of scope

The prune: auto default of 500 blocks is shorter than an epoch on every chain, which is what makes an epoch's start block get pruned before the allocation closes. That needs a per-chain or time-based minimum and is a separate decision, as the issue notes.

get_proof_of_indexing only compared the requested block to the deployment's
head. A block below earliest_block_number has had its causality-region digests
removed by pruning, so the query at that block returns an incomplete set and
ProofOfIndexingFinisher hashes it into a well-formed but wrong POI. Nothing
downstream can tell that apart from a correct one — not the operator's other
nodes, since they prune the same blocks and agree.

Return an error instead, and say which block is the earliest still available.
get_public_proof_of_indexing goes through the same path, so it inherits this.

A deployment with indexerHints.prune: auto keeps GRAPH_MIN_HISTORY_BLOCKS
(default 500, about 100 minutes on mainnet) of history. An allocation that
closes after its epoch's start block has been pruned was submitting that wrong
value, which has happened in production and been disputed.

Signed-off-by: 梁旭 <liangxu.5@bytedance.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

proofOfIndexing returns an incorrect POI for pruned blocks instead of an error

1 participant