VerificationBenchmarksPricingDemo
Log InGet API Key

Broken Chain Detection

Version: 1.0.0
Status: Production
Last Updated: 2026-05-23
Editor: Eric Beans, H33.ai, Inc.
Canonical URL: https://h33.ai/verification/broken-chain/

1. Scope

This walkthrough demonstrates how a HATS verifier detects a chain discontinuity caused by a deleted node. The original session contained three nodes (indices 0, 1, 2). Node 1 has been removed from the bundle, leaving only nodes 0 and 2. Node 2's predecessor_hash still references the hash of the deleted node 1, creating a gap in the chain.

The expected verifier output is CHAIN_BREAK at position 2 (the first node whose predecessor cannot be resolved).

2. Definitions

Chain Discontinuity
A state where a node's predecessor_hash does not match the SHA3-256 digest of the immediately preceding node in the bundle. Indicates that one or more intermediate nodes have been removed.
Node Deletion Attack
An adversarial operation where one or more governance nodes are removed from a bundle to hide attested actions. The HATS hash chain detects this because the predecessor link of the node following the deleted node(s) will reference a hash that does not correspond to any node present in the bundle.
Predecessor Resolution
The process of matching a node's predecessor_hash field against the computed hash of the preceding node in the bundle. If the preceding node's hash does not match, the chain is broken.

3. Input Bundle

The following bundle contains only two nodes: the original node 0 and the original node 2. Node 1 (COMPUTE_EXECUTE) has been deleted. Note that node indices have been renumbered to 0 and 1, but the predecessor_hash of the second node still references the deleted node's hash.

broken-chain.json
{ "schema_version": "1.0.0", "bundle_id": "b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d", "session_id": "s-20260515-143000-a1b2c3", "tenant_id": "t-9f8e7d6c-5b4a-3c2d-1e0f-a9b8c7d6e5f4", "created_at": "2026-05-15T14:30:00.000Z", "nodes": [ { "node_index": 0, "action_type": "POLICY_BIND", "payload_hash": "a3f1b2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1", "timestamp": "2026-05-15T14:30:00.000Z", "predecessor_hash": "0000000000000000000000000000000000000000000000000000000000000000", "node_hash": "c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7", "signatures": { "ml_dsa_65": "ML-DSA-65:3045022100...truncated...b8c9d0e1f2", "falcon_512": "FALCON-512:3045022100...truncated...a1b2c3d4e5", "slh_dsa": "SLH-DSA-SHA2-128f:3045022100...truncated...f6a7b8c9d0" } }, { "node_index": 1, "action_type": "RESULT_RECORD", "payload_hash": "f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6", "timestamp": "2026-05-15T14:30:02.891Z", "predecessor_hash": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5", "node_hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1", "signatures": { "ml_dsa_65": "ML-DSA-65:3045022100...truncated...d0e1f2a3b4", "falcon_512": "FALCON-512:3045022100...truncated...c3d4e5f6a7", "slh_dsa": "SLH-DSA-SHA2-128f:3045022100...truncated...b8c9d0e1f2" } } ] }

Node 1's predecessor_hash is e5f6a7b8...d4e5, which was the node_hash of the deleted COMPUTE_EXECUTE node. The actual preceding node in the bundle (node 0) has node_hash = c7a8b9d0...f6a7. These do not match.

4. CLI Command

$ hats verify broken-chain.json

5. Detection Mechanism

5.1. Chain Validation Algorithm

For each node at position i > 0, the verifier:

  1. Retrieves the predecessor_hash from node i.
  2. Computes the SHA3-256 digest of node i-1's canonical serialization.
  3. Compares the two values.
  4. If they differ, reports CHAIN_BREAK at position i.

5.2. Comparison Table

FieldExpected (from node 0)Declared (in node 1)Match
predecessor_hash c7a8b9d0e1f2a3b4...e5f6a7 e5f6a7b8c9d0e1f2...d4e5 NO

The expected predecessor hash is the SHA3-256 of node 0's canonical serialization (c7a8b9d0...e5f6a7). The declared predecessor hash in node 1 is e5f6a7b8...d4e5, which corresponds to the deleted node. The mismatch proves that at least one node was removed between nodes 0 and 1.

5.3. What the Verifier Cannot Determine

The verifier detects that a chain break occurred but cannot determine:

These limitations are inherent to hash-chain integrity checking. The verifier reports the structural fact; interpretation is the auditor's responsibility.

6. Expected Output

stdout
$ hats verify broken-chain.json HATS Verifier v1.0.0 Bundle: b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d Session: s-20260515-143000-a1b2c3 Checking schema .............. OK Checking chain integrity ..... FAILED CHAIN_BREAK at position 1: predecessor_hash declared: e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5 predecessor_hash expected: c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7 preceding node hash: c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7 Result: CHAIN_BREAK Position: 1 (node_index: 1, action_type: RESULT_RECORD) Gap: predecessor references hash not matching any adjacent node Impact: Bundle integrity cannot be established; one or more nodes missing Duration: 3ms

7. JSON Output

{ "status": "CHAIN_BREAK", "bundle_id": "b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d", "failure": { "type": "CHAIN_BREAK", "position": 1, "node_index": 1, "action_type": "RESULT_RECORD", "declared_predecessor": "e5f6a7b8c9d0e1f2...d4e5", "expected_predecessor": "c7a8b9d0e1f2a3b4...f6a7", "message": "Predecessor hash at position 1 does not match hash of preceding node. One or more nodes may have been deleted." }, "nodes_checked": 2, "chain_links_checked": 1, "chain_links_passed": 0, "duration_ms": 3 }

8. Comparison: Chain Break vs. Tampered Receipt

A chain break and a tampered receipt produce different failure types and are detected by different checks:

PropertyChain BreakTampered Receipt
Detection checkChain integrityNode hash verification
Failure typeCHAIN_BREAKNODE_HASH_MISMATCH
Root causeMissing node(s)Modified field(s)
Signatures affectedNot checked (halted at chain)All signatures on tampered node
Node content preservedNo (deleted)Yes (modified)

9. Conformance

A verifier implementation is conformant with this walkthrough if, given the input bundle above, it produces the CHAIN_BREAK status at position 1 (or position 2 if using 1-indexed positions, with the position value documented). The declared and expected predecessor hashes MUST be included in the failure output.

Conformance test vector ID: HATS-VW-003-BROKEN-CHAIN