> For the complete documentation index, see [llms.txt](https://stair-ai.gitbook.io/stair-ai-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stair-ai.gitbook.io/stair-ai-docs/protocol/verification.md).

# Tamper detection and verification

Verification is binary. Hash a retrieved trace, compare against the on-chain *Merkle root*, equality means byte-identical. There is no judgment call to make.

{% hint style="info" %}
**Merkle root.** A single cryptographic hash that summarizes a set of records. Any change to any record produces a different root, so the root acts as a tamper-detection fingerprint for the whole set.
{% endhint %}

```mermaid
sequenceDiagram
  participant V as Verifier
  participant DA as DA layer
  participant L1 as L1 blockchain
  V->>DA: Retrieve trace bundle by Blob ID
  DA-->>V: Trace JSON bytes
  V->>V: Hash bytes locally
  V->>L1: Read anchor (Merkle root, Blob ID)
  L1-->>V: Anchor commitment
  V->>V: Compare hash to Merkle root
  alt match
    Note over V: trace verified
  else mismatch
    Note over V: tampering detected
  end
```

## Step by step

1. **Verifier → DA layer**: "give me the trace bundle for Blob ID X."
2. **DA layer → Verifier**: returns the JSON bytes (the reasoning record).
3. **Verifier hashes the bytes locally**: runs the bytes through a hashing function, gets a fingerprint.
4. **Verifier → L1**: "give me the anchor for this trace."
5. **L1 → Verifier**: returns the anchor, which contains the original fingerprint that was written when the trace was created.
6. **Verifier compares**: is the fingerprint just computed the same as the one on the blockchain?
7. **Two outcomes**:
   * **Match** → the file on the DA layer is byte-identical to what was originally written. Trace verified.
   * **Mismatch** → someone altered the bytes after the fact. Tampering detected.

## The Merkle commitment

A session's records are leaves in a Merkle tree. The root of that tree is the single hash committed on the L1 blockchain. Three properties follow:

| Property                              | Why it matters                                                                                                                 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Single-record tampering is detectable | Modifying any record changes its leaf hash, which propagates to the root.                                                      |
| Single-record verification is cheap   | A verifier can prove one record belongs to the bundle with a Merkle proof of log₂N hashes, without retrieving the full bundle. |
| Anchor size is constant               | Whether a session has 5 records or 500, the on-chain footprint is the same.                                                    |

The Trace Ledger entry stores `(agent_id, session_id, merkle_root, walrus_blob_id, anchor_author_address, anchored_at_utc)`. The DA Blob ID is itself a content hash, so the upload step is verifiable independently of who initiated it.

## Self-verification flow (chain-reader SDK)

Partners verify anchor state without trusting the Trace Service via the v2 chain-reader SDK component:

```typescript
import { ChainReader } from "@stairai/chain-reader-sdk";  // v2

const reader = new ChainReader({ network: "sui_mainnet" });

const anchor = await reader.getAnchor({ agent_id, session_id });
// { merkle_root, walrus_blob_id, anchor_author_address, anchored_at_utc, sui_tx_id }

const bundle = await reader.fetchBundle(anchor.walrus_blob_id);
const ok = reader.verifyMerkle(bundle, anchor.merkle_root);  // boolean
```

Three things travel together: the anchor (proves the bundle existed at a public timestamp), the bundle (the trace bytes), and the proof (any verifier can recompute). None require Stair AI to be online.

## What verification does and does not prove

| Question                                                          | Answered by verification?                                          |
| ----------------------------------------------------------------- | ------------------------------------------------------------------ |
| Were the records altered after anchoring?                         | Yes — Merkle hash equality                                         |
| Did the records exist at the anchored timestamp?                  | Yes — L1 block timestamp                                           |
| Was the agent honest about the data it consumed?                  | No — see [zkTLS in roadmap](/stair-ai-docs/roadmap/attestation.md) |
| Was the trace produced by the same code that produced the action? | No — see [TEE in roadmap](/stair-ai-docs/roadmap/attestation.md)   |

The first two are closed by the v2 anchoring pipeline. The last two are Phase 3 attestation work, tracked separately in [Attack surfaces and mitigations](/stair-ai-docs/protocol/attack-surfaces.md).
