Skip to main content

Proof of Index

SubQuery TeamAbout 2 min

Proof of Index

Proof of Index (PoI) refers to a mechanism where the SubQuery Data Indexing SDK records the actions of updating, writing, and deleting data in the database during the indexing process. For each processed block height, these actions and the processed data are hashed in a specific order, resulting in a deterministic unique hash value. This hash value serves as proof that the node has completed the full data indexing process.

**Proof of Indexes are only used for data indexing, they do not apply to data nodes or RPC nodes.

Why do we need a Proof of Index?

In the SubQuery network, multiple Node Operators provide indexed data for the same project.

For a given project (identified by a fixed IPFS CID), we expect all Node Operators to ensure data quality by adhering to CIA principles (Consistency, Integrity, and Accuracy). When multiple Node Operators provide indexed data for the same project, maintaining the CIA of indexed data becomes a challenge. By comparing the PoI hash values at specified block heights, we can verify the trustworthiness of the data up to that height.

If all Node Operator's PoI values match, we can consider that they have reached consensus and we can guarantee that their data is the same.

Is there a possibility of data tampering or deception in Proof of Index?

Unless Node Operators maliciously modify the data in the database, PoI can greatly ensure the CIA of the data. When generating the PoI for block height n, the PoI for height n-1 is also hashed, similar to the design of blockchain. If the data is incomplete or maliciously modified, we can detect forks in the PoI hash results. By repeatedly verifying the results of these forks, we can ultimately achieve data consensus.

How do we calculate the PoI?

Users and Node Operators do not need to manually calculate PoI. PoI is automatically generated by SubQuery nodes during the indexing process based on the type of actions processed and the data. Users only need to be concerned with the result of PoI, such as the PoI hash and its parentHash, indexed block hash, operation hash. Logic/code can be found in poi/PoiBlock.tsopen in new window.

PoI: The PoI is obtained by combining various block attributes (such as block ID, on-chain block hash, operationHashRoot, project ID, and parent PoI hash) and performing a hash operation on them. This ensures that the hash generated with the same data is unique.

operationHashRoot: Records a hash of database mutations of indexed data generated from the Merkle tree. The operationHashRoot is generated by converting each store/database operation into a Uint8Array and adding it to the Merkle tree; the final operationHashRoot is generated from the tree. This keep the integrity and order of all operations.