Authenticate — Trustless Initiation Proof

These examples run against Sepolia testnet (network="sepolia"). To run against Base mainnet: replace configure(network="sepolia") with configure(network="base"). All function calls, record structures, and output shapes are identical across networks.

Every content anchor in AnchorRegistry carries a tokenCommitment — a keccak256(K || arId) hash stored immutably on Base.

The ownership token K = keccak256(salt) is generated in the browser at registration time from 32 uniform random bytes and never transmitted to AnchorRegistry servers. Only the token holder can produce the pre-image. This makes the proof trustless: no AnchorRegistry infrastructure needed, no trust required.

Two verification levels:

  • ``authenticate_anchor`` — verify a single anchor was initiated by the token holder

  • ``authenticate_tree`` — verify tree ownership (Layer 1) + every anchor in the tree (Layer 2)

[1]:
# Cell 1 — setup
# Explorer: https://sepolia.basescan.org/
from anchorregistry import configure, authenticate_tree, authenticate_anchor, BASE_SEPOLIA_RPC, V1A_BASE_SEPOLIA
configure(
    network="base-sepolia",
    contract_address=V1A_BASE_SEPOLIA,
    rpc_url=BASE_SEPOLIA_RPC,  # swap for Infura / Alchemy URL for faster scans
)

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[1], line 3
      1 # Cell 1 — setup
      2 # Explorer: https://sepolia.basescan.org/
----> 3 from anchorregistry import configure, authenticate_tree, authenticate_anchor, BASE_SEPOLIA_RPC, V1_BASE_SEPOLIA
      4 configure(
      5     network="base-sepolia",
      6     contract_address=V1_BASE_SEPOLIA,
      7     rpc_url=BASE_SEPOLIA_RPC,  # swap for Infura / Alchemy URL for faster scans
      8 )

ImportError: cannot import name 'V1_BASE_SEPOLIA' from 'anchorregistry' (/Users/ian_moore/repos/ar-python/src/anchorregistry/__init__.py)
[ ]:
# Cell 2 — authenticate a single anchor
# Replace ownership_token and ar_id with your own values
result = authenticate_anchor(
    ownership_token="0xf4accdf917e8cf2b9e0ceb0b281fba1c1a176f8922fb5eb432bfa0a5664b0680",
    ar_id="AR-2026-dPXazj6"
)
result
[ ]:
# Cell 3 — authenticate full tree
# Layer 1: keccak256(K || rootArId) == treeId
# Layer 2: verify every user-initiated anchor in the tree
result = authenticate_tree(
    ownership_token="0xf4accdf917e8cf2b9e0ceb0b281fba1c1a176f8922fb5eb432bfa0a5664b0680",
    root_ar_id="AR-2026-dPXazj6"
)
result
[ ]:
# Cell 4 — cron job audit pattern
# Run this on a schedule to continuously verify your tree hasn't been tampered with
import os
result = authenticate_tree(
    ownership_token=os.environ.get("ANCHOR_OWNERSHIP_TOKEN", "0xf4accdf917e8cf2b9e0ceb0b281fba1c1a176f8922fb5eb432bfa0a5664b0680"),
    root_ar_id="AR-2026-dPXazj6"
)
if not result["authenticated"]:
    print(f"AUDIT FAILED — {result['anchors_failed']} anchors unverified")
else:
    print(f"AUDIT PASSED — {result['anchors_verified']} anchors verified")

The verification above ran entirely against the Base blockchain. No AnchorRegistry servers involved.

One ownership token proves the entire tree is yours.

treeId          = keccak256(K || rootArId)    → tree ownership
tokenCommitment = keccak256(K || childArId)   → per-anchor initiation

Same ownership token K. Same construction. One key proves everything.

To dispute a tokenCommitment: produce the ownership token K such that keccak256(K || arId) == tokenCommitment. Producing this token proves you initiated the registration. The proof is on Base — permanent and independent of AnchorRegistry infrastructure.