Tensile is Huginn Tech's open-source explorer for Celestia Fibre. It follows blob settlements, publishers and validators in real time, and checks that every validator serves the rows it endorsed.
Mainnet · Mocha testnet · Methodology · API
- Real time. Blocks are read the moment the node announces them, so a new blob is on the site within seconds and the live pages update on their own; the API streams the newest block and blob as server-sent events.
- Every blob, searchable. Find any blob by its blob ID (base64 or hex), transaction hash, commitment or payment promise hash.
- Settlements, publishers and escrow. Each settlement with its namespace, size, fee and endorsements; who pays for blobs, and their escrow deposits, withdrawals and balances.
- Validators, checked. Endpoint reachability, TLS identity, upload readiness, and whether each validator serves the rows it endorsed.
- Where Fibre runs. Every registered Fibre host on a map, and the hosts by hosting provider, country and AS.
- An open record. A public API, Atom feeds of network and validator events, and signed daily exports, with a tool that recomputes every result from the exports.
Settlements, endorsements, protocol parameters and escrow balances are read from the chain. On top of that, Tensile runs two checks of its own: every registered Fibre endpoint is checked every five minutes (reachability, TLS identity and, from celestia-app v10.5 on, upload readiness), and every blob is read once before its retention window ends, asking each validator that endorsed it for its own rows and verifying them against the commitment. The methodology covers timing, rules and result classes.
Requires Go 1.26.10 or newer, Node 22 and make. Build from a full checkout:
fibre-sentinel finds its sibling modules through relative replace
directives.
make build # binaries in fibre-sentinel/bin/ and the site in web/out/
make clean # remove bothTo run and configure an observer (one VM with systemd and Caddy, or docker
compose), see the deployment guide, deploy/README.md.
| module | what it is | dependencies |
|---|---|---|
fibre-tlsverify |
verifies the TLS identity a Fibre server presents (consensus-key signed extension, no CA) | stdlib only |
fibre-assign |
recomputes which validator must serve which rows; ShardMap.Verify classifies what one returned |
stdlib only (the differential test in reftest/ pulls celestia-app) |
fibre-sentinel |
the observer: chain scanner, prober, heartbeat, collector, store, verdicts, exports and API | celestia-app (pinned) and the two above |
fibre-devnet |
a multi-validator local devnet with retention at the 10-minute protocol floor, for end-to-end tests | shell and a celestia-app build |
web |
the explorer: a static Next.js export that reads the API | Node 22 |
fibre-tlsverify and fibre-assign are modules of their own, which other Go
code can use from a checkout of this repository through a replace directive.
The observer runs as five processes over one data directory:
chain ──► scanner ────┐
prober ─────┼──► record files ──► collector ──► SQLite ──► API ──► site
heartbeat ──┘ └──► signed daily exports
The scanner reads each block as it arrives. The prober reads every blob before
its window ends, and the heartbeat checks every endpoint; both talk to the
validators' Fibre servers. All three append to record files, which the
collector loads into SQLite, rolls up by day and exports; it also places each
Fibre host by provider, country and AS from local IP databases that a daily
job refreshes, so no lookup leaves the host. The API serves that
database read-only, and the site is a static export that calls it. Record
files, schema, invariants and the path from a block to a figure are in
docs/SYSTEM.md.
celestia-app v10.6.0 (commit 25f09cab3f8912bbe78c62909e8d39d8fa8b3fc0),
the release mainnet and Mocha run; celestia-core v0.42.8, cosmos-sdk fork
v0.52.12. TLS golden vectors come from celestia-app commit
dba155084505a8f6c5d37260a94f70f939fb96de.
fibre-assign/reftest/go.mod and fibre-sentinel/go.mod each carry a copy of
celestia-app's replace block; refresh the pin and the block together.
make verify # unit tests, script checks and the web build: what CI runsBesides the build requirements it needs python3 and curl. shellcheck
runs when installed; CI always runs it.
The end-to-end devnet run starts four validators, publishes three blobs,
stops one validator's Fibre server and checks every reading. It needs
celestia-appd and fibre on PATH:
make devtestTo re-derive every verdict and obligation figure from a record or an untarred daily export, and compare it with the API at the same moment:
cd fibre-sentinel && go run ./cmd/sentinel-recompute -data-dir <dir> -window 7d -as-of <RFC3339> -api https://tensile.huginn.tech/api- Methodology: what every figure means, how it is computed and what it counts.
- API: every endpoint, with real responses.
docs/SYSTEM.md: how the running system fits together: processes, record files, store and invariants.docs/verdicts.md: every outcome and classification a request can get, and how each one counts.docs/exports-signing.md: the signed daily exports, and how to verify them offline.deploy/README.md: running an observer: configuration, systemd and Caddy or docker compose, backups and checks after deploy.
Each network's daily exports are signed with its own key. The API serves the
public keys; check them against these fingerprints, which are kept here so a
reader has a copy that does not come from the API
(docs/exports-signing.md).
| Network | Key fingerprint |
|---|---|
| Mainnet | sha256:59fc7c28a1df95f8ec512a09404c670318241c9ce16a767132a002b7e6a72e1f |
| Mocha | sha256:8eb4c98fd59e067ce8651f0edec06bcccc6d92b49b2ddd8161929ec3826a5412 |
Report bugs and suggest changes in GitHub issues; pull requests are welcome.
-
Code: Apache-2.0. See also
NOTICE. -
Data: CC BY 4.0 for Tensile's own figures on the site, in the API and in the exports, credited as "Data from Tensile by Huginn Tech".
