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:
- Hash — the session record is hashed into a leaf node using SHA-256
- Batch — the leaf is included in a Merkle tree with other sessions from the same time window; the Merkle root is computed
- 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.jsonRecompute 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:
- The session record you have is byte-for-byte identical to what was ingested — it has not been modified
- That session record was included in a specific batch — it was not injected post-hoc
- 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
- Compliance Evidence Export — export the evidence bundle this guide uses
- Blockchain Anchoring — how the anchoring pipeline works
- SDK Utilities Reference —
compute_merkle_root_hex,verify_proofAPI details