Blockbook v0.6.0
A major release bringing Tron network support, ERC-4626 vault enrichment, an ENS resolver, extensive performance, reliability, and security hardening, and a large wave of backend node upgrades.
New Features and Chain Support
- Tron network support (#1273): adds Tron support to Blockbook.
- Split bandwidth into staked and free fields (#1444): separates Tron account bandwidth into
stakedandfreefields for clearer resource accounting. - Tx balance history maps freezing, unfreezing and voting rewards (#1463): correctly maps Tron freeze/unfreeze operations and voting rewards as incoming/outgoing in balance history.
- Recognize account activation transactions (#1466): adds
AccountCreateContractparsing so Tron account-activation transactions are no longer shown as unparsed. - Expose staking and voting data in account API (#1467): implements
TronStakingInfoinTronAccountExtraDataexposing staking and governance data via the account API. - Extend account data with total energy and bandwidth (#1547): adds total energy and total bandwidth to
TronAccountExtraData. - Expose latestWithdrawTime in staking info (#1604): adds
latestWithdrawTimeparsed fromlatest_withdraw_timeto Tron account staking information.
- Split bandwidth into staked and free fields (#1444): separates Tron account bandwidth into
- Opt-in ERC-4626 vault enrichment for EVM tokens (#1431): adds REST/WS
protocols=erc4626batched vault detection and response enrichment underprotocols.erc4626. - Stateful ERC-4626 persistent cache with multicall batching (#1502): replaces per-request sequential
eth_calls with a block-pinned, singleflight-deduped, reorg-safe persistent cache using Multicall3 batch aggregation; eliminates virtually all RPC overhead for vault enrichment. - ENS resolver (#1289): resolves ENS names in the EVM explorer and API.
- Ethereum Hoodi testnet support (#1328): adds configuration and support for the new Hoodi Ethereum testnet.
- Alternative RPC provider for transaction broadcast (#1264): allows sending transactions to the mempool via an alternative (e.g. MEV-protected/private relay) provider.
- Initialize alternative providers for EVM chains (#1322).
- Per-request opt-out flag (#1313):
sendTransactionaccepts JSON with adisableAlternativeRPCparameter. - Use alternative provider URL for simulation and nonce (#1316) and
eth_getTransactionCountwith pending tag (#1314): keeps nonce/simulation consistent with privately submitted transactions. - Scope alternative provider usage (#1330): stops routing
eth_callandeth_gasPricethrough the alternative provider.
- Unconfirmed balance reporting (#1142): improves unconfirmed balance handling in the API.
- Alternative fee estimation: mempool.space median (#1233): adds a new
mempoolspacemedianoption for thealternative_estimate_feesetting. - longTermFeeRate WebSocket endpoint (#1262): exposes a long-term fee rate estimate over WebSocket.
- Return fees lower than 1 sat/vB (#1335): allows sub-1 sat/vB fee estimates to be returned.
- Publish confirmed transactions by address (#1198): WebSocket subscribers can receive confirmed transaction notifications per address.
- Avalanche priority fees (#1376): adds Avalanche priority fees and corrects existing fee values.
- EVM block-gas data for EIP-1559 fee projection (#1586): adds
baseFeePerGas,blockGasUsed, andblockGasLimittosubscribeNewBlocknotifications so wallets can project EIP-1559 base fees deterministically. - EVM getContractInfo endpoint (#1477): adds a single-contract lookup endpoint so clients can refresh ERC-4626 vault data and fiat pricing without reloading full
accountInfo; unifies protocol enrichment shape betweengetAccountInfoandgetContractInfo(#1480 removes the resultingContractInfoduplication from API types). - Basic detail for stakingPools (#1338): adds basic detail level to staking pool responses.
- Method-selector allowlist for rpcCall (#1597): adds
ALLOWED_EVM_CALL_METHODSconfiguration allowingrpcCallto invoke whitelisted 4-byte selectors on any address; runtime-configurable via admin API. - WebSocket connection caps (#1483): adds per-IP connection limits with configurable trusted-proxy origin detection for more reliable client-IP attribution.
- Rate-limit WebSocket and REST API traffic (#1563): adds application-level abuse protection with per-connection WS message-rate limits, per-client REST request throttling, shared trusted-proxy attribution, and bounded balance-history queries per transport.
- Expose confirmed nonce on address API (#1562): adds the confirmed account nonce to the address API response for EVM chains.
- ERC-4626 support in explorer (#1431, #1502): see above; vault data is also surfaced in the explorer UI.
Performance
- Concurrent internal-data fetching in GetBlock (#1383): runs
processEventsForBlockandgetInternalDataForBlockconcurrently. - GetBlock no longer unmarshals the same raw JSON twice (#1385).
- Replace per-contract eth_call with multicall for ERC-20 (#1388): batches ERC-20 contract reads through Multicall.
- Faster BTC mempool resync with batching + outpoint cache (#1403): adds optional batch tx fetch with bounded concurrency and a temporary resync outpoint cache to avoid repeated parent lookups.
- Ethereum address-contract indexing micro-optimizations (#1417): adds hot-address LRU/index map to remove O(n) contract scans, bounds cache growth, and improves ERC20 aggregation hot-path overhead.
- AddrContractsCache to speed up indexing (#1323): caches address-contract records during EVM indexing.
- WebSocket/API perf + fiat observability improvements (#1423): batches fiat enrichment with robust fallback reasons, improves client-facing error behavior, and reduces log noise.
- Memory optimizations (#1479): addresses agent-discovered heap-pressure findings, reducing overall memory footprint.
- Skip mempool tx body loading for AccountDetailsBasic (#1499): drops per-tx body fetch for
details=basicWebSocket requests; reportsunconfirmedTxsfrom cheap mempool-index length only, saving significant RPC work on mempool-heavy addresses. - Accumulate address-hotness hits across blocks (#1529): makes the contract-index LRU promotion counter persist across blocks instead of resetting per block, so hot-address detection works on lower-throughput chains too.
- Websocket communication optimizations (#1550): reuses the xpub best-height within a request across derived addresses, adds a WebSocket write-buffer pool, reduces subscription lock hold time, and caches merged confirmed xpub txids for unfiltered paged requests.
- Resolve tx inputs without unpacking full prev-tx records (#1595): reads only the single needed output per input instead of unpacking the entire previous transaction, eliminating quadratic heap allocation on high-fan-in addresses.
- Improve WebSocket GetBlock pagination defaults (#1476): replaces the 1M-transaction default page size with a sane bound matching the REST interface.
Reliability and Correctness
- Fix initialization of Ethereum RPC (#1307, #1321).
- Fix EthereumTypeGetNonce (#1327).
- Improved error handling and logging (#1326): better readability of EVM RPC errors in logs.
- UTXO reorg detection fix (#1398): fixes reorg detection on UTXO chains.
- Avoid Base newHeads bursts (#1407): debounces bursty
newHeadsnotifications on Base. - Dual (WS/HTTP) rpc_client support (#1400): allows separate WebSocket and HTTP RPC endpoints for EVM backends.
- Reliable SIGTERM shutdown + clean RocksDB close (#1408): reworks signal fan-out so main shutdown always runs, unblocks workers, and stops periodic state writes during shutdown.
- Resync recovery on errors (#1409): detects errors in parallel/bulk sync and triggers controlled resync restarts on rollback/reorg to avoid infinite retry stalls.
- Fixed scientific notation parsing error (#1429):
AmountToBigIntnow safely handles scientific notation (e/E), keeps a fast path for plain decimals, and rejects pathological exponent expansion. - Fix Nillion (NIL) token decimals (#1443): adds the Nillion
NILERC-20 contract to the contract-fix config withdecimals: 6, correcting misscaled balance/transfer amounts. - Don't lowercase Base58 Tron token addresses for fiat rates (#1458): stops case-sensitive Base58 Tron contract addresses from being lowercased during fiat-rate lookups (which broke their rate resolution), while hex EVM tokens keep lowercase normalization.
- Skip ZMQ initialization when message_queue_binding is empty (#1460): enables ZMQ-less operation with zebrad by skipping zmq_connect("") instead of returning EINVAL.
- Accept BTC non-standard tx versions outside int32 range (#1478): decodes
getrawtransactionJSON version as uint32 to fix "Transaction not found" for historical bitcoin transactions whose version exceeds int32 max. - Retry unfinalized RPC responses (#1489): maps Avalanche "cannot query unfinalized data" errors to
ErrBlockNotFoundinstead of swallowing them, preventing trace-length mismatches during sync. - Fix fiat rates: change platform currency from eth to usd (#1495): corrects the fiat-rate query currency for token rates; requires running
reset_eth_token_rates.shafter deploy. - Stop ERC20 batch fallback from amplifying RPC calls (#1501): prevents a single bad batch response from triggering per-contract
eth_callfallbacks that amplified failed requests into N+1 RPCs. - Deduplicate address descriptors and fix confirmed-block matching (#1508): deduplicates subscriber addresses before counting and restricts confirmed-block tx conversion to
publishNewBlockTxssubscribers, reducing expensive receipt RPCs. - Retry transient missing-tip block fetches before ResyncIndex (#1517): retries transient
ErrBlockNotFoundinside the sequential sync loop instead of unwinding to the fullResyncIndexpath, preventing slowdowns on load-balanced RPC tip skew. - Fix NFT self-transfer reorg rollback (#1525): corrects ERC-721/1155 ownership rollback when a self-transfer block is disconnected during reorg.
- Fix config propagation duck-typing issue (#1528): fixes a structural-typing mismatch that prevented certain config values from being propagated.
- Prevent sync stalls on load-balanced EVM RPC skew (#1530): makes EVM sync tolerate load-balanced backend tip height inconsistencies and prevents the parallel/bulk coordinator from wedging when workers report abort conditions.
- Heal silently-stalled EVM newHeads tip feeds (#1533): adds a chain-aware staleness watchdog that detects when the push feed goes silent without raising
sub.Err()and heals it, preventing undetected sync stalls. - Make CoinGecko fiat-rate fetching resilient to 429 throttling (#1560): adds a self-healing pass for missing daily rates at startup and improves resiliency of fiat rates fetching.
- Reconcile the alternative-provider send-tx mempool cache (#1562): re-checks liveness and heals nonce-superseded entries in the self-maintained alternative/private-relay send-tx cache (which relays don't expose for sync), with new metrics; no API/wire change.
- Keep alt-mempool txs visible when private relay stops surfacing them (#1572): defers eviction of alt-mempool txs to the absolute cache timeout when
eth_getTransactionByHashreturns empty from private relays, preventing premature disappearance. - Tron: polling-only tip sync fallback when ZeroMQ is unavailable (#1578): adds a polling fallback for Tron tip sync when the node runs the MongoDB event plugin instead of the native ZMQ queue.
- Always serialize token decimals, default unresolved to coin convention (#1579): removes
omitemptyfrom token decimals so clients can distinguish 0-decimal tokens from missing metadata; defaults unresolved values to 18 for ERC-20. - Tron: keep receipt logs from unsolidified blocks (#1583): retains receipt data for not-yet-solidified Tron blocks so token transfers are indexed immediately instead of waiting for solidification.
- Send a Blockbook user-agent on CoinGecko requests (#1589): adds a
User-Agentheader to CoinGecko fiat-rate requests to avoid being blocked/throttled, complementing the 429-resilience work in #1560. - Prevent panic parsing non-32-byte-aligned EVM input data (#1591): fixes an index-out-of-range panic when transaction input data is not aligned to 32-byte words.
- Disable mempool sync on remaining L2 configs (#1599): sets
disableMempoolSync: truefor OP Stack and Arbitrum configurations where the backend does not supportnewPendingTransactionssubscriptions. - Avoid int64 overflow in on-chain base fee conversion (#1605): uses
big.Int.SetUint64forbaseFeePerGasinstead of int64 cast, preventing negative values on high-fee L2s. - Fix PIVX Sapling txid computation (#1607): computes the correct canonical txid for PIVX Sapling transactions (v>=3) by hashing the entire raw transaction bytes instead of just the decoded portion.
- Recover GetTransaction on archive backends with pruned tx index (#1610): falls back to reconstructing the transaction from its receipt and block body when
eth_getTransactionByHashreturns null on backends with pruned transaction hash indexes. - Prevent slice-bounds panic from ENS log name-length overflow (#1613): guards against a crafted ENS
NameRegisteredlog causing alow > highslice expression, fixing an unauthenticated availability DoS that could crash the EVM sync goroutine. - Prevent duplicate ERC-721 holdings (#1624): makes ERC-721 holding insertion idempotent so a replayed
Transferlog can't credit the same token ID twice, preserves holdings across self-transfers and their reorg rollback, and adds a read-only RocksDB checker that reports (but never repairs) existing duplicates. - Gate alternative-provider nonce lookups to recent private senders (#1628): stops routing every
eth_getTransactionCountto the alternative provider when*_ALTERNATIVE_SENDTX_URLSis set, restricting it to senders with a recent privately submitted tx — avoiding provider rate-quota exhaustion, 429 log floods, and stale pending nonces. - Rename ETH contract 0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb to Fluid (#1334).
Security
- Potential DoS fix for oversized pagination inputs (#1363): validates extreme
pageandpageSizevalues to prevent resource-exhaustion requests. - Security hardening: CSP + XSS fixes in templates (#1397): adds CSP headers and fixes XSS vulnerabilities in templates.
- Escape HTML in token name and symbol shown in explorer (#1346).
- WebSocket origin allowlist (#1421): adds optional origin checks with explicit logging to reduce cross-origin websocket exposure when not protected by a proxy.
- Request-size and template hardening (#1434): limits
/api/sendtxbody size, rejects oversized websocket messages, and avoidstemplate.JSStr. - Limit fiat timestamp requests (#1520): adds a 1000-timestamp maximum for fiat-rate batch lookups and a global WebSocket active-request limit.
- Limit xpub descriptor expansion (#1521): bounds xpub change-list expansion before account scans, caps the in-memory xpub cache size, and evicts LRU entries.
- Fix XSS in xpub explorer descriptor handling (#1552): anchors the xpub descriptor regex with a terminal
$and avoids rendering user-supplied strings throughtemplate.JSStrin the QR-code JavaScript expression. - CI/CD security hardening (#1553): pins actions and dependencies to full commit SHAs, adds dependabot, verifies Go tarball and backend artifact checksums, restricts workflow permissions, and adds opt-in TLS verification for deploy scripts.
- Upper-cap limits on WebSocket endpoints (#1582): caps in-flight mempool-filters responses per connection, bounds fiat-rate currency selectors, and hardens ERC-1155
TransferBatchlog parsing against OOM from malformed data. - Quote paths in root logrotate cleanup (#1602): prevents arbitrary recursive deletion by quoting log paths in the root cron logrotate script, fixing a local privilege-boundary issue reachable from the Blockbook service user.
- Cap subscribeFiatRates tokens array length (#1623): adds a 1000-token maximum for
subscribeFiatRatesWebSocket requests, consistent with existing caps on other list parameters.
Observability
- Syncing/caching Prometheus metrics (#1420): introduces many new metrics for syncing throughput and cache behavior.
- WebSocket/API perf + fiat observability improvements (#1423): adds Prometheus metrics for fiat enrichment and API behavior.
- Metric for alternative fee-provider requests (#1485): adds a Prometheus counter tracking alternative fee-provider request outcomes, labeled by provider and status.
- Graceful consensus node monitoring degradation (#1488): marks the consensus node as
"unreachable-locally"on dev instances when not running locally, reducing maintenance overhead while preserving production visibility. - Observe JSON-RPC calls for block sync (#1527): adds error-request metrics for JSON-RPC calls made during block sync.
- Auto-generated Grafana dashboard from source of truth (#1541): generates the Grafana dashboard from
metrics.yamlandpanels.yamlto eliminate duplication; adds four new WebSocket abuse-observability metrics (connection requests, rejections, unique IPs, per-IP connection count). - Correct stale EIP-1559 max-fee panel (#1596): fixes an incorrect instant-tier claim in the EIP-1559 max-fee Grafana panel description.
- Sync RPC latency metric (#1601): adds a Prometheus latency histogram for sync-internal RPC calls.
Fiat Pipeline
- Plan-aware CoinGecko API handling (#1370): detects the CoinGecko API plan and adjusts endpoints, request pacing and headers accordingly.
- Adjusted Infura request periods (#1269).
- Extract fiat rates from worker.go with more tests (#1424): moves fiat-rate logic into a dedicated component and expands test coverage.
- See also the CoinGecko 429-resilience (#1560), user-agent (#1589) and platform-currency (#1495) fixes under Reliability and Correctness.
Configuration and Deployment
- Configurable backend RPC endpoints for builds/tests (#1392): adds per-coin
BB_RPC_URL_*overrides for non-local backends,BB_RPC_BIND_HOST_*/BB_RPC_ALLOW_IP_*for safer network exposure, plusrpc_url_ws_templateandBB_RPC_URL_WS_*overrides. - Override Message Queue URL from environment variables (#1468): allows overriding the message queue connection URL via environment variables without modifying coin config.
- Configurable debouncedelay; increased defaults for Polygon and Arbitrum (#1475): makes the newHeads debounce delay configurable and increases defaults for Polygon and Arbitrum to tolerate frequent short reorgs; adds explicit
trace_timeoutfor heavydebug_traceBlockByHashcalls. - Decrease mempool timeout for MEV-protected coins (#1500): reduces the stale-tx eviction timeout for alternative/private relay mempool entries that expire faster than the public mempool.
- Runtime env via optional EnvironmentFile (#1574): adds an optional
EnvironmentFile=/etc/blockbook/blockbook.envto the systemd unit so runtime config no longer requires hand-editing/etc/systemd/system.conf. - Extend rate limiting to cover all dynamic routes (#1588): replaces the
/api-only rate-limit allowlist with a deny-all-except-static gate, covering explorer UI routes alongside REST API routes. - Tune REST/UI rate-limit defaults for individual user traffic (#1590): adjusts per-client rate-limit defaults to 20 req/min with burst 20, matching individual browsing patterns rather than high-throughput clients.
- Make WebSocket per-connection pending-request limit configurable (#1626): exposes the previously hard-coded
maxWebsocketPendingRequests(48) as a per-coin env knob so self-hosted batch consumers pipelining many requests over one connection are no longer disconnected mid-batch. - Configurable per-coin xpub expansion and cache caps (#1630): replaces the hard-coded xpub cache-size, expiration, and max-derivation constants with a per-coin
XpubConfig, and raises the default cache to 1024 entries to stop thrashing under many concurrent users. - Support no-compression RocksDB builds on Windows (#1259).
Build and CI/CD
- New GitHub Actions build → deploy pipeline (#1426, #1437, #1438, #1439, #1447, #1448, #1453, #1471): full build/deploy workflows for prod and dev, including backend building, post-deploy sync waiting and filtered E2E validation.
- Deploy with dpkg (#1446): packages deployments as Debian packages.
- Remove legacy GitLab CI, improve Python setup (#1551).
- CI/CD pipeline review fixes (#1603) and workspace-local npm cache (#1615).
- Upgrade Go to 1.25 and dependencies (#1367): also fixes Avalanche sync.
- Resolve Arbitrum, Base, and Zcash build errors (#1325).
Testing
- API-level E2E suite + deploy workflow (#1426): adds E2E tests against live Blockbook endpoints plus GitHub Actions build/deploy stages that wait for sync and run filtered E2E validation after deploy.
- Tron E2E API tests (#1440): adds E2E tests for Tron API endpoints.
- Ethereum Classic integration tests (#1454): adds integration tests covering Ethereum Classic RPC and API endpoints.
- ERC-4626 E2E tests (#1511): adds E2E tests for the ERC-4626 vault enrichment protocol.
- OpenAPI specification + swagger endpoint with TS-compiled verification (#1523): introduces an
openapi.yamlspec served via swagger-ui, separates E2E tests from integration tests, and adds CI/CD verification thatblockbook-api.tsis type-compatible. - Extend E2E suite with fiat rate and WebSocket tests (#1539): adds fiat-rate freshness and validity checks plus WebSocket block/balance-history/tx tests; produces jUnit XML test reports for CI visibility.
- Agentic local testing (#1514) and local env var cleanup (#1516): improves the local testing workflow.
- System check for local test prerequisites (#1564): adds a pre-check that validates the local environment meets testing requirements, with clear error messages for missing dependencies.
- Testnet integration/E2E tests (#1575): adds integration and post-deploy E2E coverage for Sepolia, Hoodi, and Nile testnets; fixes a matchable-name collision that caused sibling testnets to share one subtest name.
- Parallelize E2E test suite (#1601): runs E2E tests across coins in parallel, adds proactive sample preloading and persistent WebSocket connections.
- Ethereum/Tron presets in test-websocket page (#1464) and sendTransaction test with disableAlternativeRPC flag (#1320).
- Raise fiat concurrency-test drain timeout (#1614) and widen block-index search window for ETC tests (#1616): reduce CI flakiness.
Backend Updates
- Bitcoin (+testnets): 29.0 → 29.2 (#1343)
- Ethereum — erigon (+testnets): 3.0.1 → 3.3.3 and latest (#1245, #1249, #1263, #1266, #1279, #1282, #1331, #1333, #1339, #1348, #1399, #1455, #1462)
- Ethereum — prysm (+testnets): 5.3.2 → 7.1.0 and latest (#1240, #1246, #1256, #1268, #1344, #1378, #1455, #1462)
- Polygon — bor: 2.0.1 → 2.2.9 (#1254, #1275, #1285, #1288); heimdall 1.2.2 → 1.6.0 (#1284) and migration to Heimdall v2 (#1293)
- Zcash: 6.1.0 → 6.2.0 (#1243), then migrated from zcashd to Zebra (#1292) with subsequent upgrades 2.4.2 (#1295), 2.5.0 (#1324), 3.0.0 (#1365), 4.1.0 (#1402), 4.4.1 (#1504), 4.5.0 (#1532), 5.0.0 (#1544); ZebraRPC adjusted for the new backend (#1377); testnet migrated to Zebra 5.0.0 for NU6.2 (#1548)
- Bitcoin Cash: 28.0.1 → 29.0.0 (#1505)
- Groestlcoin: bump to 29.0 (#1248, #1251)
- Firo: 0.14.14.1 (#1278), 0.14.15.0 (#1349), 0.14.15.3 (#1432) — mandatory updates
- Flux: v8.0.0 (#1306), v9.0.0 (#1350), v9.0.5 (#1359)
- Qtum: bump to 29.1 (#1364)
- Tron testnet (Nile): backend 4.8.2 (#1611); shortcut/network renamed to
tTRX(#1470)
Documentation
Removed
- Remove obsolete Socket.IO interface (#1487): drops the deprecated Socket.IO transport, no longer used by any client.
Housekeeping
- Code comment fixes (#1229, #1267),
slices.Clonerefactor (#1244), built-inmax/minusage (#1319), version bump to 0.6.0 (#1425), unreleased changelog update (#1625).
New Contributors
- @cranycrane made their first contribution in #1272
- @highcloudwind made their first contribution in #1229
- @etimofeeva made their first contribution in #1295
- @emersonian made their first contribution in #1325
- @gcmutator made their first contribution in #1267
- @careworry made their first contribution in #1244
- @wmypku made their first contribution in #1319
- @pragmaxim made their first contribution in #1392
- @RampantDespair made their first contribution in #1370
- @matusbalascak made their first contribution in #1444
- @tuan-phan made their first contribution in #1460
- @sneurlax made their first contribution in #1548
- @h45hc47 made their first contribution in #1578
- @Aharonee made their first contribution in #1595
- @knaperek made their first contribution in #1626
Full Changelog: v0.5.0...v0.6.0