Continuity Proving for Query

The Creditcoin Decentralized Oracle uses Continuity proving to determine whether a block is part of certified source chain. It is the first of two key proofs that certify oracle results.

Overview

Continuity proofs for queries are cryptographic proofs that link the queried source chain block to an on-chain attestation or checkpoint, establishing that the block is part of the finalized source chain. This is essential for trustless cross-chain verification because it proves that the block containing the queried transaction has been attested to by the Creditcoin Oracle and cannot be reverted.

circle-info

Note: Continuity proof generation for queries differs from continuity proofs used in attestation generation (see Continuity Proving for Attestation). This section focuses specifically on query continuity proofs.

Continuity Proof

A continuity proof for a query cryptographically links the queried block to an attestation or checkpoint stored on Creditcoin. The proof structure contains:

  • lowerEndpointDigest: The digest of the block before the query (queryHeight - 1), retrieved from indexed attestation data on Creditcoin

  • roots[]: An array of Merkle roots for blocks from queryHeight to the attestation/checkpoint block

Digests are computed on-chain from these roots using this formula, which creates an unbroken cryptographic chain: digest[i] = hash(blockNumber[i], merkleRoot[i], digest[i-1])

Why Continuity Proofs Are Needed

Without continuity proofs, a malicious prover could:

  • Present fake Merkle roots for non-existent blocks

  • Claim transactions exist in blocks that were never finalized

  • Use outdated or reorganized blocks

Continuity proofs solve this by:

  1. Linking to On-Chain Attestations by proving the queried block is part of a client source chain that has been attested to on Creditcoin

  2. Creating Cryptographic Guarantees through the digest chain that provides cryptographic proof that blocks form an unbroken, tamper-proof sequence from the lower endpoint to the attestation/checkpoint

Query Types

The Proof Generation API supports two types of continuity proof queries:

1. Query Between Attestations:

  • The query block falls between two regular attestations

  • The API queries indexed attestation data on Creditcoin

  • Constructs a continuity proof using computed roots and digests from the indexed attestations

  • The proof links from the lower attestation to the upper attestation

2. Query Between Checkpoints:

  • The query block falls between two checkpoints (which are filtered attestations)

  • The API queries all attestations in that range from the indexed data on Creditcoin

  • Creates the continuity proof based on all attestations in the checkpoint interval

  • The proof ends in a checkpoint, providing stronger finality guarantees

In both cases, the API queries indexed data stored on Creditcoin (attestations and checkpoints) and constructs the continuity proof using the computed roots and digests from this indexed data.

Continuity Proof Construction

When an off-chain worker needs to query a transaction at a specific block height, the Proof Generation API constructs a continuity proof through the following steps:

1. Determine Interval Endpoints

The API first identifies the attestation/checkpoint boundaries around the query:

  1. Find the Highest Attestation/Checkpoint Before the Query

    • Queries indexed attestation/checkpoint data stored on Creditcoin

    • Identifies the most recent attestation or checkpoint with a block number less than queryHeight

    • Retrieves the computed digest from the indexed data to use as lowerEndpointDigest

  2. Find the Lowest Attestation/Checkpoint After the Query

    • Queries indexed attestation/checkpoint data on Creditcoin for the earliest attestation or checkpoint with a block number greater than or equal to queryHeight

    • The proof must link to this attestation/checkpoint's digest

    • This serves as the upper endpoint of the continuity proof

    • For queries between checkpoints, this will be a checkpoint (ending in a checkpoint)

Example:

  • Query height: 145

  • Last attestation before query: Block 140 (digest: 0xabc...)

  • Next attestation after query: Block 150 (digest: 0xdef...)

  • Continuity proof must link blocks 145-150 to attestation at block 150

2. Query Indexed Data and Fetch Source Chain Blocks

The API queries indexed attestation data on Creditcoin and fetches source chain blocks:

  1. Query Indexed Attestation Data:

    • For queries between attestations: Retrieves the specific attestations from indexed data

    • For queries between checkpoints: Queries all attestations in the checkpoint interval range from indexed data

    • Uses the computed roots and digests from the indexed attestation data

  2. Fetch Block Headers

    • Requests block headers from the source chain RPC node

    • Needs blocks from queryHeight to the next attestation/checkpoint block

    • Each block header contains: block number, Merkle root, previous block hash

  3. Verify Block Integrity

    • Validates that blocks form a continuous chain

    • Ensures each block's previousBlockHash matches the previous block's hash

    • This ensures blocks haven't been tampered with or reorganized

Example (continuing from above):

  • Queries indexed attestation data on Creditcoin for blocks 140-150

  • Fetches blocks: 144, 145, 146, 147, 148, 149, 150

  • Blocks 145-150 form the chain to the attestation

3. Construct Digest Chain

The API constructs the digest chain using the computed roots and digests from the indexed attestation data on Creditcoin:

Digest Calculation Formula:

Where:

  • blockNumber[i] is the block number (e.g., 145)

  • merkleRoot[i] is the Merkle root from the block header

  • digest[i-1] is the digest of the previous block

Process:

  1. Start with the digest of the block before the query (queryHeight - 1)

    • This digest should match the prev_digest from the attestation/checkpoint before the query

    • If no previous attestation exists, use genesis digest

  2. For each block from queryHeight to the attestation/checkpoint block, compute using roots from indexed data:

  3. The final digest (digest[150]) must match the digest stored in the indexed attestation/checkpoint data on Creditcoin at block 150.

4. Build Continuity Proof Structure

The continuity proof structure is simplified and only stores Merkle roots (digests are computed on-chain):

Continuity Proof Structure:

  • lowerEndpointDigest: The digest of the block before the query (queryHeight - 1)

    • This is the prev_digest that the first block in the continuity chain references

    • Must match the digest from the attestation/checkpoint before the query

  • roots[]: Array of Merkle roots for blocks from queryHeight to the attestation/checkpoint block

    • Block numbers are derived: blockNumber = queryHeight + index

    • Digests are computed on-chain from these roots (not submitted in proof)

Security

The fundamental security property of continuity proofs is the cascading effect of digest changes:

If any block in the continuity proof is modified:

  1. The digest of that block changes (because it includes the block's Merkle root)

  2. All subsequent block digests change (because each digest includes the previous digest)

  3. The final digest will not match the on-chain attestation/checkpoint digest

  4. This mismatch can be detected during verification, causing the proof to be rejected

Example Attack Scenario:

Last updated