- Docs
- Infrastructure
- Proof Verification
Proof Verification
Learn how to verify the integrity of actions and state on the Dual platform using Merkle proofs and zero-knowledge proofs.
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
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 and Complexity
Logarithmic space, grows slowly with batch size:
Tree Depth: log₂(N)Proof Size: 32 × log₂(N) bytesFor 10,000 actions: ~5.3 KB proof
Verification Algorithm
To verify a Merkle proof:
- Compute the leaf hash from action data (
orgId || actionId || timestamp || payloadHash) - Obtain the Merkle proof (array of sibling hashes from leaf to root)
- Hash upward along the proof path:
hash(leaf, sibling₁)→hash(result, sibling₂)→ ... - 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 actionconst 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:
checkpointRootpreviousStateRootfinalStateRootactionCount
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 actionclient.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 sequencerconst { proof, checkpointRoot } =await client.sequencer.getProof(actionId);// Step 2: Verify the proofconst isValid = await client.sequencer.verifyProof({actionId,proof,checkpointRoot,});// Step 3: Show result to userif (isValid) {showVerifiedBadge(actionId);console.log("✓ Cryptographically verified");} else {showErrorBadge(actionId);console.log("✗ Verification failed");}return isValid;}// Call it after action confirmationawait client.actions.submit(actionData);await verifyAction("action-id-12345");
Webhook Integration
Auto-verify when checkpoints confirm:
// Listen for checkpoint.confirmed webhookapp.post("/webhooks/checkpoint", async (req) => {const { checkpointId, actions } = req.body;// Verify all actions in the checkpointconst 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 databaseawait 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
Use when: Early development, internal testing, low-stakes transactions
Level 2: Merkle Trust
Trust cryptographic math, not Dual.
Trust Assumption: SHA-256 is secure
Use when: Production apps, user-facing transactions, external audits
Level 3: On-Chain Trust
Trust the blockchain, not Dual.
Trust Assumption: Blockchain consensus
Use when: Institutional settlement, regulatory compliance, high-value assets
Related Topics
- Sequencer, Checkpoint creation and ordering
- ZK Rollup, Proof generation on-chain
- Smart Contracts, Verifier contracts