Proof Verification

Verify the integrity of any action on the DUAL platform. Two types of cryptographic proofs—Merkle inclusion and zero-knowledge validity—enable investors, developers, auditors, and regulators to independently confirm that actions were processed correctly and state is tamper-proof.

Why Verification Matters

Trust in the DUAL platform is not blind. Every action can be independently verified using cryptographic proofs. Instead of relying on DUAL's assertions, you can perform mathematical verification that proves:

  • Don't trust, verify: Anyone can independently confirm the platform state without relying on DUAL's word.
  • No reliance on DUAL: Cryptographic proof is mathematical certainty. The proofs are valid even if DUAL goes offline or acts maliciously.
  • Regulatory value: Auditors and regulators can verify platform state without accessing sensitive data. Proofs are non-interactive and tamper-proof.
  • Investor confidence: Proof of correctness is embedded in the platform. Institutional participants can rely on cryptographic guarantees, not trust.

Key Metrics

Proof Types

2

Merkle inclusion + ZK validity

Verification Cost

~300K gas

On-chain ZK verification

Proof Size

~200 bytes

Merkle proof (log n depth)

Trustless

Yes

Fully independent verification

Two Types of Proof

DUAL uses two complementary proof systems to enable trustless verification:

Merkle Inclusion Proofs

Prove that a specific action is part of a checkpoint Merkle tree.

How it works:

Path from leaf (action hash) to root (checkpoint hash)

When to use:

"Was my transaction included?"

Proof size:

O(log n) - typically 200-300 bytes

Leaf → Sibling₁ → Sibling₂ → ... → Root ✓

ZK Validity Proofs

Prove that all state transitions in a checkpoint are valid.

How it works:

ZK-SNARK verifies computation without replaying it

When to use:

"Were all rules followed?"

Verification:

Single elliptic curve pairing check

Proof + Public Input → Verifier → ✓/✗

Merkle Proof Deep Dive

Merkle proofs allow you to prove that a specific action was included in a checkpoint without downloading the entire batch. They are small, fast to verify, and work off-chain or on-chain.

Leaf Hash Construction

Each leaf is a SHA-256 hash of action metadata:

leafHash = SHA256(
orgId || actionId || timestamp ||
payloadHash
)

Proof Size & Complexity

Logarithmic space—grows slowly with batch size:

Tree Depth: log₂(N)
Proof Size: 32 × log₂(N) bytes
For 10,000 actions:
~5.3 KB proof

Verification Algorithm

To verify a Merkle proof:

  1. 1.Compute the leaf hash from action data (orgId || actionId || timestamp || payloadHash)
  2. 2.Obtain the Merkle proof (array of sibling hashes from leaf to root)
  3. 3.Hash upward along the proof path: hash(leaf, sibling₁) → hash(result, sibling₂) → ...
  4. 4.Verify the computed root matches the on-chain checkpoint root

This computation is O(log N) and requires only the Merkle proof and the checkpoint root—no need to download the entire batch.

Code: Verifying a Merkle Proof

Using the DUAL SDK:

import { DualClient } from "dual-sdk"; import crypto from "crypto"; const client = new DualClient({ token: process.env.DUAL_API_KEY, authMode: "api_key", }); // Get the Merkle proof for an action const proofData = await client.sequencer.getProof( "action-id-12345" ); // Manually verify (optional—SDK does this automatically) function verifyMerkleProof( leaf, proof, root ) { let hash = leaf; for (const sibling of proof) { hash = crypto .createHash("sha256") .update(Buffer.concat([hash, sibling])) .digest(); } return hash.equals(root); } const isIncluded = verifyMerkleProof( proofData.leafHash, proofData.proof, proofData.checkpointRoot ); console.log(isIncluded ? "✓ Included" : "✗ Not found");

ZK Validity Proof Deep Dive

Zero-knowledge proofs prove that all state transitions in a checkpoint are valid without replaying the computation. This enables regulators and auditors to verify correctness independently.

What the Circuit Proves

  • Signature validity: All action signatures are cryptographically valid and signed by authorized parties
  • State transitions: All state transitions follow template rules and ownership constraints
  • No double-spends: No token is transferred or burned twice in the same checkpoint
  • State root: Final state root matches the claimed state root hash

Public Inputs

Known to both prover and verifier:

checkpointRoot
previousStateRoot
finalStateRoot
actionCount

Verification

Performed via DUALVerifier contract:

verify(proof,
publicInputs)
→ bool

Code: Verifying On-Chain

Call the DUALVerifier contract directly using ethers.js:

import { ethers } from "ethers"; const provider = new ethers.JsonRpcProvider(RPC_URL); const verifier = new ethers.Contract( DUAL_VERIFIER_ADDRESS, VERIFIER_ABI, provider ); const publicInputs = [ checkpointRoot, previousStateRoot, finalStateRoot, actionCount ]; const isValid = await verifier.verify( zkProof, publicInputs ); if (isValid) { console.log("✓ ZK proof verified on-chain"); } else { console.log("✗ Proof verification failed"); }

Verification Workflows

Different workflows for different use cases:

Developers

Verify via API

GET /sequencer/proof/:actionId

Fetch Merkle proof for a single action and verify off-chain using SDK methods.

Auditors

Bulk verification

GET /sequencer/checkpoints/:id

Download a checkpoint and verify all proofs in batch. Stream actions and verify state transitions.

Regulators

On-chain verification

DUALVerifier.verify()

Call the verifier contract directly. No API access needed—verification is independent of DUAL servers.

Users

End-user flow

App webhook

Application automatically verifies proof when checkpoint is confirmed. Display verified badge in UI.

Building Verification Into Your App

Integrate proof verification into your application to show users that their actions are cryptographically verified.

SDK Methods

client.sequencer.getProof(actionId)

Fetch the Merkle proof for a given action

client.sequencer.verifyProof(proof, root)

Verify a Merkle proof against a checkpoint root (off-chain)

client.sequencer.getCheckpoint(checkpointId)

Fetch full checkpoint metadata and actions

Full Example: Fetch and Verify

End-to-end verification flow:

async function verifyAction(actionId) { // Step 1: Get the proof from the sequencer const { proof, checkpointRoot } = await client.sequencer.getProof(actionId); // Step 2: Verify the proof const isValid = await client.sequencer.verifyProof({ actionId, proof, checkpointRoot, }); // Step 3: Show result to user if (isValid) { showVerifiedBadge(actionId); console.log("✓ Cryptographically verified"); } else { showErrorBadge(actionId); console.log("✗ Verification failed"); } return isValid; } // Call it after action confirmation await client.actions.submit(actionData); await verifyAction("action-id-12345");

Webhook Integration

Auto-verify when checkpoints confirm:

// Listen for checkpoint.confirmed webhook app.post("/webhooks/checkpoint", async (req) => { const { checkpointId, actions } = req.body; // Verify all actions in the checkpoint const results = await Promise.all( actions.map(async (action) => { const isValid = await client.sequencer .verifyProof({ actionId: action.id, proof: action.proof, checkpointRoot: action.checkpointRoot, }); return { actionId: action.id, verified: isValid }; }) ); // Mark actions as verified in your database await markActionsVerified(results); });

UI Pattern: Verification Status Badge

Display verification status in your UI:

function ActionRow({ action, verified }) { return ( <div className="flex items-center gap-3"> <span>{action.description}</span> {verified ? ( <span className="badge verified"> ✓ Verified </span> ) : verified === false ? ( <span className="badge error"> ✗ Failed </span> ) : ( <span className="badge pending"> ⏳ Verifying... </span> )} </div> ); }

Trust Model

DUAL offers multiple trust levels. Choose the one appropriate for your risk model:

Level 1: API Trust

Trust DUAL's API response directly.

Trust Assumption:
DUAL server is honest

Level 2: Merkle Trust

Trust cryptographic math, not DUAL.

Trust Assumption:
SHA-256 is secure

Level 3: On-Chain Trust

Trust the blockchain, not DUAL.

Trust Assumption:
Blockchain consensus

When to Use Each Level

API Trust:

Early development, internal testing, low-stakes transactions

Merkle Trust:

Production apps, user-facing transactions, external audits

On-Chain Trust:

Institutional settlement, regulatory compliance, high-value assets

Related Topics