Skip to Content
GuidesBlockchain Verification

Blockchain Verification

Every session record anchored by VeriProof can be independently verified — by you, by a regulator, or by a third-party auditor — without access to the VeriProof platform. The verification uses the exported Merkle proof and a public Solana transaction lookup.

This guide walks through the full verification procedure.


What you are verifying

A VeriProof compliance record goes through three stages before verification is possible:

  1. Hash — the session record is hashed into a leaf node using SHA-256
  2. Batch — the leaf is included in a Merkle tree with other sessions from the same time window; the Merkle root is computed
  3. Anchor — the Merkle root is written to Solana via a Compressed Merkle Tree (CMT) transaction

Verification checks the chain in reverse: starting from the raw session record, recompute the leaf hash, reconstruct the Merkle proof, and confirm the root exists in the Solana transaction.


Before you start

You need:

  • The exported evidence bundle (JSON format) for the session — see Compliance Evidence Export
  • Python 3.9+ with the VeriProof SDK installed (pip install veriproof-sdk)
  • Internet access to query the Solana RPC (or a local Solana RPC node)

Verification walkthrough

Obtain the evidence bundle

Export the JSON bundle for the session from the Customer Portal, or via the API:

curl -s \ -H "Authorization: Bearer your-portal-jwt" \ -H "X-API-Key: your-secondary-api-key" \ "https://portal.veriproof.app/api/sessions/SESSION_ID/evidence?format=json" \ -o evidence_SESSION_ID.json

Recompute the leaf hash

import json from veriproof import compute_merkle_root_hex with open("evidence_SESSION_ID.json") as f: evidence = json.load(f) session_record = evidence["session_record"] computed_leaf_hash = compute_merkle_root_hex([session_record]) expected_leaf_hash = evidence["merkle_proof"]["leaf_hash"] if computed_leaf_hash != expected_leaf_hash: print("FAIL: Session record has been modified since anchoring") print(f" Computed: {computed_leaf_hash}") print(f" Expected: {expected_leaf_hash}") else: print(f"PASS: Leaf hash matches — {computed_leaf_hash}")

If this check fails, the session record has been altered. The data in the evidence bundle does not match what was anchored.

Verify the Merkle proof

from veriproof import verify_proof proof_valid = verify_proof( leaf_hash=evidence["merkle_proof"]["leaf_hash"], proof_path=evidence["merkle_proof"]["path"], root=evidence["merkle_proof"]["root"], ) if not proof_valid: print("FAIL: Merkle proof invalid — session leaf not in this batch root") else: print(f"PASS: Merkle proof valid — root is {evidence['merkle_proof']['root']}")

Confirm the root on-chain

Look up the Solana transaction ID from the evidence bundle:

anchor = evidence["anchor"] print(f"Transaction ID: {anchor['transaction_id']}") print(f"Block: {anchor['block']}") print(f"Timestamp: {anchor['anchored_at']}") print(f"Expected root: {evidence['merkle_proof']['root']}")

Then verify the transaction on-chain using the Solana Python client:

from solana.rpc.api import Client client = Client("https://api.mainnet-beta.solana.com") tx = client.get_transaction(anchor["transaction_id"], encoding="jsonParsed") # The Merkle root is stored in the transaction instruction data # Extract and compare with evidence["merkle_proof"]["root"] instruction_data = tx.value.transaction.message.instructions[0].data print("Transaction instruction data:", instruction_data)

The exact location of the Merkle root within the instruction data depends on the CMT program version. The evidence bundle includes a verification_notes field describing the offset and encoding. The PDF export includes a pre-formatted verification summary for non-technical reviewers.

Alternatively, look up the transaction manually on a block explorer:

  • Solana Explorer: https://explorer.solana.com/tx/{transaction_id}
  • Solana FM: https://solana.fm/tx/{transaction_id}

What a passed verification proves

A verification that passes all three checks establishes the following:

  1. The session record you have is byte-for-byte identical to what was ingested — it has not been modified
  2. That session record was included in a specific batch — it was not injected post-hoc
  3. That batch’s Merkle root was written to the Solana blockchain at a specific time by a specific transaction — the timestamp is immutable and publicly verifiable

This chain of proof does not require any trust in VeriProof’s infrastructure. It only requires trust in the SHA-256 hashing algorithm and the Solana blockchain.


Automated verification at scale

For audit workflows that need to verify many sessions:

import json from pathlib import Path from veriproof import compute_merkle_root_hex, verify_proof results = [] for evidence_file in Path("audit_export").glob("evidence_*.json"): with open(evidence_file) as f: evidence = json.load(f) session_id = evidence["session_record"]["session_id"] # Step 1: Leaf hash computed = compute_merkle_root_hex([evidence["session_record"]]) expected = evidence["merkle_proof"]["leaf_hash"] hash_ok = computed == expected # Step 2: Proof path proof_ok = verify_proof( leaf_hash=expected, proof_path=evidence["merkle_proof"]["path"], root=evidence["merkle_proof"]["root"], ) results.append({ "session_id": session_id, "hash_matches": hash_ok, "proof_valid": proof_ok, "anchor_tx": evidence["anchor"]["transaction_id"], }) print(f"{session_id}: hash={'PASS' if hash_ok else 'FAIL'}, proof={'PASS' if proof_ok else 'FAIL'}") # Summary passed = sum(1 for r in results if r["hash_matches"] and r["proof_valid"]) print(f"\n{passed}/{len(results)} sessions verified successfully")

FAQ

Is verification possible if VeriProof is offline or shut down?

Yes. The blockchain anchor is permanent and publicly accessible on Solana regardless of VeriProof’s status. The SHA-256 and Merkle algorithms are standard and do not depend on VeriProof software. As long as you have the evidence bundle (store it yourself), you can verify it forever.

What if the Solana explorer does not show the transaction?

Transactions older than ~2 years may not be indexed by all Solana block explorers, but they remain in the blockchain state. Use an archival RPC node or run your own Solana validator with full ledger history for long-term access. The transaction ID in the evidence bundle is permanent.

Can I verify without using the VeriProof SDK?

Yes. The compute_merkle_root_hex function is a standard SHA-256 Merkle computation over the canonical JSON serialization of the session record. The technical specification for the canonical form is published at docs.veriproof.app/security/blockchain-anchoring .


Next steps

Last updated on