Verification & Proofs
Proof Hashes
Every verified delta produces a proof hash that is deterministic, tamper-evident, and chain-linked.
When PacSpace verifies a delta, it produces a proof hash — a cryptographic value that lets you independently confirm your data was recorded accurately. Every proof hash has three fundamental properties.
Three Properties of Proof Hashes
Deterministic
Given the same input data, the proof hash is always the same. There's no randomness, no timestamps mixed into the hash, no server-specific variation. You can recompute it yourself and get the exact same result every time.
Same delta payload → Same content hash → Same proof hash
This means verification is repeatable. Today, tomorrow, a year from now — the math always checks out.
Tamper-Evident
Change a single byte of the original data and the proof hash is completely different. There's no way to make a "small" change that preserves the hash. This property makes it immediately obvious if data has been altered after verification.
Original: { "amount": 42.50 } → 0x8f3a9b...
Tampered: { "amount": 42.51 } → 0xd17c4e... ← completely different
Chain-Linked
Each proof hash includes a reference to the previous proof hash. This creates a sequential chain where every delta is cryptographically tied to the one before it. You can't insert, remove, or reorder deltas without breaking the chain.
proofHash₀ ← proofHash₁ ← proofHash₂ ← proofHash₃
If someone tampers with delta 1, then delta 2's previousProofHash no longer matches — and the break is detectable all the way forward.
Independent Verification
You don't need to trust PacSpace. When you receive a delta.verified webhook, you get everything needed to verify the proof yourself. Here's how:
Step 1: Recompute the content hash
Take the original delta payload, canonicalize it, and hash it using the same algorithm PacSpace uses (see the Merkle Specification for exact details).
import { createHash } from 'crypto';
function computeContentHash(deltaPayload) {
const canonical = JSON.stringify(deltaPayload, Object.keys(deltaPayload).sort());
const prefixed = 'pacspace:item:v1:' + canonical;
return keccak256(prefixed);
}
const myHash = computeContentHash({
customerId: 'cust_8xKj2m',
amount: -42.50,
reason: 'usage_charge',
referenceId: 'inv_20260211_001',
metadata: { plan: 'growth' }
});
Step 2: Confirm your content hash is in the batch
Check that your computed content hash appears in the itemHashes array from the webhook payload. This proves your delta was included in the batch.
const { itemHashes, contentHash } = webhookData.proof;
// Your recomputed hash should match the contentHash from the webhook
assert(myHash === contentHash, 'Content hash mismatch — data may have been altered');
// And the contentHash should be present in the batch
assert(itemHashes.includes(contentHash), 'Content hash not found in batch');
Step 3: Recompute the Merkle root
Build a Merkle tree from the full itemHashes array using the Merkle Specification rules, and compute the root.
const recomputedRoot = computeMerkleRoot(itemHashes);
Step 4: Confirm it matches the proof hash
Compare your recomputed root against the proofHash from the webhook. If they match, the batch is verified.
const { proofHash } = webhookData.proof;
assert(
recomputedRoot === proofHash,
'Proof hash mismatch — batch integrity check failed'
);
Step 5 (optional): Validate the chain link
If you stored the previous delta's proof hash, confirm it matches previousProofHash to verify chain continuity.
const { previousProofHash } = webhookData.proof;
assert(
previousProofHash === storedPreviousProofHash,
'Chain broken — previous proof hash does not match'
);
Verification Summary
| Check | What it proves |
|---|---|
| Content hash recomputation | Your original data is unchanged |
Presence in itemHashes | Your delta was included in the batch |
| Merkle root recomputation | The batch hasn't been tampered with |
| Proof hash comparison | The committed proof matches the batch |
| Chain link validation | No deltas were inserted, removed, or reordered |
Next Steps
- Merkle Specification — The exact hashing rules and reference implementations
- Webhook Payloads — Full schema for the
delta.verifiedevent
Last updated February 11, 2026