Pool OffChain Data
July 16, 2026 ยท View on GitHub
(as of 13.2.0.0 Offline was renamed to OffChain)_
When a stake pool is registered, a transaction is added to the chain containing the URL of the pool's offchain data.
The data in the transaction specifying the location of the offchain data is inserted into the
PoolMetadataRef table. db-sync then fetches the specified data and inserts it into the
OffChainPoolData table.
The basic operation is a follows:
- When the pool registration is found in a tx it is inserted into the
PoolMetadataReftable. - Another thread periodically queries the database for
PoolMetadataRefentries which have either not been retrieved or have errored and tries to fetch the data. - If the new fetch is successful, the result goes in the
OffChainPoolDatatable. - If the fetch fails, an error is recorded in
PoolOffChainFetchError tableto be retried later. - The retries on fetch fail start at 60 seconds and are progressively longer and eventually plateau at a retry every 24 hours.
http-get-json-metadata
This is a testing/debugging program. It uses the same code to fetch the offchain metadata as
cardano-db-sync. It is not a code copy, this application calls the functions in db-sync that do
the actual fetch (httpGetOffChainPoolData and httpGetOffChainVoteData in
Cardano.DbSync.OffChain.Http).
On a successful network fetch (pool metadata, or governance metadata with the url keyword) this
program prints "Success" and then the retrieved JSON. On failure, the error message is printed.
Reading governance metadata from a local file uses a different, more verbose output - see the
governance section below.
It is included in the release tarball alongside cardano-db-sync, or it can be run from the
cardano-db-sync git checkout with cabal run.
Pool metadata
With no type keyword, the program fetches and parses pool metadata. The program can be run as:
> cabal run -- http-get-json-metadata <url>
If you also want to check the JSON metadata hash, the program can be run as:
> cabal run -- http-get-json-metadata <url> <hash>
where the hash is specified as a string of hexadecimal digits.
If you don't know the hash, you can provide an empty string for this field and the program will print the expected hash in the error message. Eg:
> cabal run -- http-get-json-metadata https://git.io/Jt01O ""
Up to date
Hash mismatch from when fetching metadata from https://git.io/Jt01O. Expected but got
54796c0c86228b9c86a1982e76441b293d01b7a9cd1309d43ae95123a8ad8933.
You can then run the program again with the provided hash:
> cabal run -- http-get-json-metadata https://git.io/Jt01O 54796c0c86228b9c86a1982e76441b293d01b7a9cd1309d43ae95123a8ad8933
Up to date
Success
{"description":"Guaranteed lifetime 1% staking pool. Proceeds go toward crypto education.",
"homepage":"https://cardano.afterschoollabs.io","name":"After School Labs","ticker":"ASLAB"}
Governance (vote) metadata
Adding a type keyword switches the program to governance metadata, parsed according to CIP-100,
CIP-108 and CIP-119. This is the way to check how db-sync treats a given anchor before it shows up
in the database. The type keyword selects the anchor type:
drep- DRep registration metadataga- governance action metadatavote- vote metadatacommittee_dereg- committee member deregistration metadataconst- constitution metadataother- any other anchor
Add the url keyword to fetch over the network, together with one type keyword:
> cabal run -- http-get-json-metadata url drep <url>
> cabal run -- http-get-json-metadata url drep <url> <hash>
Without the url keyword, a type keyword reads from a local file instead of fetching. The path
takes the place of the URL:
> cabal run -- http-get-json-metadata drep ./drep-metadata.json
Local-file mode prints a lower-level debug dump rather than the Success line used by the network
fetch. In order, it prints: the parsed metadata as an internal record, the same file as a raw JSON
value, the file's computed blake2b-256 hash, any validation warning (Nothing if none), and finally
Is valid JSON: True. The Is valid JSON line is the pass/fail signal here, and the printed hash is
the anchor's hash - useful when you have the file but not the hash. If you pass an expected hash as a
trailing argument, a mismatch is reported in the warning slot.
ipfs:// URLs
Many real governance anchors use an ipfs://<CID> URL rather than an https:// one. The running
db-sync daemon resolves these through its ipfs_gateway config field (a list of gateway prefixes,
default ["https://ipfs.io/ipfs"]), but this debug tool passes an empty gateway list, so it
cannot resolve ipfs:// on its own. Fetching one directly fails with:
Error Offchain Voting Anchor: No ipfs_gateway provided in the db-sync config
To test an ipfs:// anchor, rewrite it into a plain gateway URL yourself before passing it in -
replace the ipfs:// scheme with a gateway prefix. The content (and therefore the hash) is the
same, so any hash check still applies:
ipfs://QmXdfDSSkR8TYBntMT4nuTL9sE9E44FJnpWVpaY8ZTfwjj
-> https://ipfs.io/ipfs/QmXdfDSSkR8TYBntMT4nuTL9sE9E44FJnpWVpaY8ZTfwjj
Note that public IPFS gateways are frequently rate-limited or briefly unavailable (HTTP 429 / 504 / timeout). A failure of that kind is a gateway problem, not a sign that the anchor or its hash is bad - retry, or try a different gateway prefix, before drawing a conclusion.
Content-type handling
The fetch checks the "content-type" field in the response headers. The rules are as follows:
application/json: This is the expected value.application/ld+json: Accepted.text/plain: Accepted.application/octet-stream: Accepted.binary/octet-stream: Accepted.application/binary: Accepted.text/html: Accepted only if it might be JSON (ie first non-whitespace character of body is{).- missing content-type header: Accepted.
- all others: Rejected.
Extra text in the content-type header field (eg charset=utf-8) is ignored.
test-http-get-json-metadata
This is a bulk health check for pool metadata. It takes no arguments and uses PGPASSFILE to
connect to an existing db-sync database. It queries every stored pool metadata reference (skipping
retired pools), re-fetches each URL with the same code as above, and prints a summary of how many
fetches failed in each error category (hash mismatch, timeout, bad content-type, and so on). It
covers pool metadata only.
> PGPASSFILE=config/pgpass-mainnet cabal run -- test-http-get-json-metadata