Skip to content

feat(insight): serve the stock Firo Insight routes and labels - #34

Merged
stultusmundi merged 5 commits into
masterfrom
feat/firo-insight-extras
Oct 29, 2026
Merged

stultusmundi merged 5 commits into
masterfrom
feat/firo-insight-extras

Conversation

@stultusmundi

Copy link
Copy Markdown
Collaborator

Lets the FIRO Insight explorer move from the stock insight-api-zcoin 0.4.5 to Blockbook's native Insight listener without breaking its callers.

How it is scoped

A chain parser that implements InsightExtension() string (server.InsightExtensionProvider) gets that named extension (server/insight_ext.go). Only FiroParser does. The extension only adds paths the generic router does not know, replaces currency, and decorates converted txs. BTC/ZEC routes, currency shape and tx output are unchanged (covered by TestInsightFiroRoutesOnlyForFiro).

Routes (server/insight_firo.go)

Route firod Cache
masternode/listmasternodes evoznodelist 30 s
masternode/listmasternodesarray[/:filter] GET + POST evoznodelist, stock filter rules 30 s
masternode/masternodecount evoznode count 30 s
currency Blockbook fiat rates, stock shape {zcoin_usd,btc_usd:0,btc_zcoin:0,bitstamp} fiat layer
ext/getmoneysupply, zerocoin/* and sigma/* totals/real supply/txids gettotalsupply, getaddressbalance/getaddresstxids of the pseudo-addresses 60 s
sparknames getsparknames 60 s

Tx output: stock labels for private spends (Zerospend, Sigmaspend, Lelantusjsplit, Sparkspend, Remint with the tx output value) and mints (zerocoinmint/Zeromint … sparksmint/Sparksmint). For a Spark spend that registers a name it adds sparkData and the synthetic first sparkname output and renumbers outputs, as stock does. getsparknametxdetails is called only for Spark spends (stock calls it for every tx) and is cached.

Differences from stock

  • id in the masternode envelopes is a listener counter, not firod's random JSON-RPC id.
  • firod errors are the listener's JSON 500 (stock echoed the error or crashed the request).
  • POST masternode/listmasternodesarray/:filter is 405 here (404 on stock).
  • POST znodes/listznodesarray is not aliased. Stock 0.4.5 answers 404 and so does this, so its callers see no change.
  • Not served: richlist, sigmastatus, lelantusstatus (Postgres-backed, broken on stock).

Fiat rates

configs/coins/firo.json gets the zcash.json-style fiat config with CoinGecko id zcoin. Follow-up: viprates.zelcore.io/v2/blockbook/api/v3/simple/price?ids=zcoin answers coin not found today. Until zcoin is enabled there, zcoin_usd stays 0, the same as stock today, and the fiat downloader logs errors.

Tests

Fixtures in server/testdata/insight_firo.json were recorded from FIRO-01 (stock API plus firod, read-only). The masternode array/list/filter cases, including the form and JSON POST, comma lists with duplicates and the [::]:0 → "[]" ip quirk, all match stock byte-for-byte apart from id. The supply and total values, txid lists and sparknames also match. As a one-off check, the full 7287-node mainnet list was byte-identical to stock. go test -tags unittest ./server/ ./bchain/coins/firo/ ./api/ ./build/tools/ . passes, and so does -race on the Insight tests. gofmt is clean.

Blockbook's native Insight listener can now stand in for the stock Firo
Insight (insight-api-zcoin 0.4.5). A chain parser that implements
InsightExtension() gets that named extension; only the Firo parser does,
so other coins keep the generic route table, currency shape and tx output.

The Firo extension serves masternode/listmasternodes,
masternode/listmasternodesarray[/:filter] (GET and POST, stock filter
rules), masternode/masternodecount, currency in the stock shape,
ext/getmoneysupply, the zerocoin/sigma supply, total and txid routes, and
sparknames, each from the firod call stock makes, cached 30-60 s. Insight
tx output gets stock's private spend/mint labels and, for Spark name
registrations, sparkData and the synthetic "sparkname" output.

configs/coins/firo.json gets fiat rates from the ZelCore rates service
(CoinGecko id zcoin), as zcash.json does.
- listmasternodesarray: cap the filter at 4 KiB and 100 distinct items
  (400 above, for body, path and query forms), dedupe items, build each
  node's searchable JSON once per cached list, stop when the request
  context ends.
- insightCached: single-flight load outside the mutex, shared result or
  error, stale-on-error, errors cached 5 s without a good value, waiters
  give up when their context ends.
- Spark names: cache only daemon answers (not transport or warm-up
  errors); two-generation bound instead of wiping all entries.
- Synthetic sparkname output writes scriptPubKey hex and asm as "", as
  stock; other outputs unchanged.
firod answers -25 both for a known tx that registers no Spark name and for a
tx it cannot find yet; caching the second would hide a name for 10 minutes.
@stultusmundi
stultusmundi merged commit d00b564 into master Oct 29, 2026
4 checks passed
@stultusmundi
stultusmundi deleted the feat/firo-insight-extras branch October 29, 2026 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant