Skip to content

chore: align master with upstream-latest#26

Merged
sidhujag merged 1093 commits into
masterfrom
fix-master-upstream-ancestry
Jun 30, 2026
Merged

chore: align master with upstream-latest#26
sidhujag merged 1093 commits into
masterfrom
fix-master-upstream-ancestry

Conversation

@sidhujag

Copy link
Copy Markdown
Member

Summary

  • Align master with the current upstream-latest tree.
  • Preserve upstream-latest as a merge parent so master is no longer behind after merge.
  • Explicitly delete stale master-only legacy files.

Verification

  • git rev-parse HEAD^{tree} equals git rev-parse origin/upstream-latest^{tree}.
  • git merge-base --is-ancestor origin/upstream-latest HEAD returns success.
  • Verified stale files are absent from the branch tree, including server/socketio.go, static/templates/tx.html, .gitlab-ci.yml, and old zcoin/zelcash files.

IMPORTANT: merge this PR with "Create a merge commit". Do not squash merge, or GitHub will lose the upstream-latest ancestry again.

Made with Cursor

* chore(erc4626): adding ws endpoint to fetch 4626 data for token

* chore(erc4626): evolve getErc4626 into getContractInfo endpoint

* chore(erc4626): unify getAccountInfo with getContractInfo

* chore(erc4626): cleanup

* chore(erc4626): add EVM-only guard for getContractInfo

* chore(erc4626): add EVM-only guard for getAccountInfo

* chore(erc4626): add tron spec to ContractInfoResult, Token and TokenTransfer
 Previously, the entire cfAddressAliases column family was loaded into a map at startup via InitAddressAliasRecords and held forever. On Ethereum mainnet (~1.5–2.5M ENS records at ~140 B/entry) this cost ~280–350 MB resident on every archive instan and there was no eviction. Replace with a 100k-entry LRU that lazy-loads on GetAddressAlias miss via a cfAddressAliases point lookup. The CF is small and bloom-filtered, so misses are sub-millisecond. The store path populates the LRU directly, keeping recently-written aliases hot. InitAddressAliasRecords and its call from LoadInternalState are removed. Negative results are not cached — addresses without an alias hit RocksDB on each render, but the CF's bloom filter makes this cheap and keeps the LRU focused on real aliases.
3x bigger db cache is not necessary anymore after recent syncing optimizations
Bitcoin mainnet contains a handful of historical transactions whose 4-byte version field, interpreted as unsigned, exceeds int32 max.
Honor X-Real-Ip when the TCP peer is on a loopback/RFC1918/ULA/link-local network, i.e. an upstream proxy on the same host or LAN. For direct internet peers the header stays ignored so it can't be used to spoof past the per-IP rate limiter. Auto-detected via netip predicates, no config.
Background ticker that calls limiter.sweep() every cleanupInterval, so TTL-expired idle entries are evicted even when no new connections arrive to drive cleanup. The goroutine is started once in NewWebsocketServer
Add <NETWORK>_WS_TRUSTED_PROXIES env var to extend X-Real-Ip trust beyond loopback/RFC1918 for non-Cloudflare deployments. Fails startup on /0 or otherwise overly broad prefixes (< /8 IPv4, < /16 IPv6) so misconfig can't silently turn the header into a spoofing primitive.
Wrap the four DB-touching go ... spawn sites with a sync.WaitGroup gate
and add WebsocketServer.Shutdown(ctx) that flips a shuttingDown flag,
closes all registered channels, and waits for in-flight goroutines to
drain. PublicServer.Shutdown now drives it after http.Server.Shutdown,
so a long getAccountInfo can no longer race rocksdb_close in cgo and
SIGSEGV on graceful restart.
pragmaxim and others added 28 commits June 23, 2026 09:23
Blockbook reads operator secrets and per-coin tunables (INFURA_API_KEY,
COINGECKO_API_KEY, <coin>_* limits, ...) from its process environment at
runtime. These were provided out of band via systemd DefaultEnvironment in
/etc/systemd/system.conf, hand-maintained per host.

Add an optional EnvironmentFile=-/etc/blockbook/blockbook.env to the blockbook
service unit so a single file can supply them per host. The leading '-' keeps
the file optional, so public/community installs and existing hosts that still
use DefaultEnvironment are unaffected when it is absent; a unit-level value also
overrides a DefaultEnvironment value for the same key, allowing a no-flag-day
migration off system.conf.

On the dev deploy path (bbcli -> deploy.yml on self-hosted runners) the file is
materialized from the BB_BLOCKBOOK_ENV GitHub Actions secret before the service
restart; the step is a no-op when the secret is unset so it is safe to merge
before the secret exists. Prod hosts will render the same file via bbctl.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The set of BB_ build-time variable prefixes was duplicated in three places that
had to be hand-synced: the Makefile forwarding regex, the export-env-vars action
normalizer, and templates.go. A drift failed silently (e.g. a var exported to
GITHUB_ENV but absent from the Makefile regex never reaches the build).

Introduce build/bb-build-var-prefixes.txt as the canonical list. The Makefile
now derives the forwarding match from it (output verified identical to the old
regex; BB_BUILD_ENV continues to be forwarded separately via -e on each docker
run), and the action reads it for coin-alias normalization. templates.go keeps
its typed constants but a new test (TestCanonicalPrefixesCoverTemplateConsumers)
asserts every prefix it relies on is present in the file, so drift now fails in
CI instead of at build time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The materialize step wrote the env file with `tee` (umask default, ~0644) and
only then chmod'd it to 0600, leaving a brief window where the secrets were
world-readable on the runner. Pre-create the file 0600 root:root with
`install /dev/null`; tee then truncates it without changing the mode, closing
the window and dropping the now-redundant chown/chmod.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sconfigured

EVM coins that set `alternative_estimate_fee` to "infura"/"1inch" require the
matching API-key env var (INFURA_API_KEY / ONE_INCH_API_KEY). Previously a
missing key only logged an error and silently reverted to default fee
estimation, so a misconfigured node started and served wrong fees.

Propagate the provider-construction error from initAlternativeFeeProvider
through the existing InitAlternativeProviders path (already checked by every EVM
coin), so a node whose config selects a provider it cannot construct fails to
start instead of degrading silently. A coin with no provider configured stays a
no-op.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The fail-fast added in c468fa3 makes EVM chain initialization abort when a
configured alternative_estimate_fee provider cannot be built because its
API-key env var is unset. Integration tests render the production coin configs
and call chain.Initialize(); avalanche selects "infura", but the test
environment is never given INFURA_API_KEY (the CI Makefile only forwards BB_*
vars), so TestIntegration/avalanche=main/rpc now fails during init.

Supply harmless placeholder keys for the EVM fee providers at the start of the
integration run so the chain initializes and falls back to default fee
estimation; the background fee fetch just 401s and is ignored. These tests
assert RPC/sync behavior, not fees, and a real key in the environment is still
respected. Production fail-fast is unchanged and covered by the unit tests in
bchain/coins/eth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
BB_BLOCKBOOK_ENV was redundant (BB already stands for Blockbook) and did not
convey that its content is the runtime environment file. Rename the GitHub
Actions secret reference to BB_RUNTIME_ENV, consistent with the new
BB_ADMIN_USER/BB_ADMIN_PASSWORD runtime variables.

The GitHub repository secret must be renamed to match; until it is, the
materialize step no-ops and leaves blockbook.env untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The internal server binds all interfaces by default (configs/coins/*:
internal_binding_template is ":<port>"), so its /admin pages and
state-mutating POST handlers (internal-data refetch, contract-info updates)
were reachable unauthenticated by any peer that could reach the port. Gate
the whole /admin surface behind HTTP Basic auth, credentials from
BB_ADMIN_USER/BB_ADMIN_PASSWORD (delivered via blockbook.env).

Basic auth (rather than a bearer token) lets the admin HTML pages and forms
be used directly from a browser via its native login prompt, and still works
for scripts via curl -u. The surface is fail-closed: unless both variables
are set, every /admin route returns 503. /metrics, the status page and
static assets are unaffected, so Prometheus scraping is unchanged.

- A trailing-slash catch-all (/admin/) is gated too, so unregistered or
  trailing-slash paths can't fall through to the unauthenticated index.
- Credentials are trimmed of surrounding whitespace at load (a stray newline
  in blockbook.env won't lock the operator out) and only their SHA-256
  digests are retained; user and password are compared in constant time with
  both comparisons evaluated before being combined.

Transport is the existing self-signed cert, intended for a trusted,
firewalled internal segment (see docs/env.md).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The /admin/ trailing-slash catch-all added to gate unknown admin subpaths
also returned 404 for a bare "/admin/", so navigating to the natural
trailing-slash URL dead-ended after login instead of showing the admin index
(served at /admin, no trailing slash). Redirect "/admin/" to the canonical
"/admin" while still returning a gated 404 for any genuinely unknown
/admin/* path, so the subtree stays authenticated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…di, nile) (trezor#1575)

* fix(tests): keep testnet network suffix in matchable test name

getMatchableName/matchable_name collapsed every "<coin>_testnet*" key to
"<coin>=test", so sibling testnets (sepolia vs hoodi, testnet vs testnet4)
shared one subtest name. The deploy connectivity regex built for one testnet
then also selected its siblings, so a deploy could fail because an unrelated
testnet's blockbook was unreachable.

Preserve the network suffix after "_testnet" so the mapping is injective
("ethereum_testnet_sepolia" -> "ethereum=test_sepolia"), and anchor each name
in the connectivity regex so "bitcoin=test" no longer substring-matches
"bitcoin=test4". Add Go and Python regression guards and update the docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(integration): add tron_testnet_nile integration tests

Mirror the mainnet tron entry (connectivity http, api, rpc). The rpc fixture
tests/rpc/testdata/tron_testnet_nile.json already exists, and the BB_DEV_*
RPC/API repository variables for tron_testnet_nile are already provisioned, so
no new GitHub variables are required.

Adding the connectivity group lets the deploy pipeline gate tron_testnet_nile
on backend + Blockbook reachability, and the api group enables the post-deploy
OpenAPI e2e suite for it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(integration): add ethereum_testnet_sepolia and _hoodi integration tests

Give both Ethereum testnets connectivity (http + ws) and the no-fixture EVM api
list (the same list used by avalanche/arbitrum/optimism). The fixture-backed EVM
tests (ERC4626, contract-info, protocols) are intentionally omitted because they
require tests/openapi/fixtures/<coin>.json with mainnet contract addresses, which
only exist for ethereum and base; no rpc group is added for the same reason
(no tests/rpc/testdata/<coin>.json fixture yet).

The BB_DEV_* RPC/API repository variables for both testnets already exist (the
RPC URLs resolve via the *_archive fallback), so no new GitHub variables are
required. Connectivity gates their deploys and api enables the OpenAPI e2e suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(integration): support disabling a coin via tests.json "disabled" flag

tron_testnet_nile's backend and Blockbook dev instance are not currently
deployed, so its connectivity/rpc/api tests cannot pass. Rather than delete
the test definitions, mark the coin "disabled": true in tests/tests.json and
teach every consumer to skip it:

- tests/integration.go skips disabled coins with a visible SKIP
- tests/openapi/src/config.ts drops disabled coins from e2e selection
- .github/scripts/runner.py treats disabled coins as non-deployable

Remove the flag to re-enable. Documented in AGENTS.md and covered by Go and
Python unit tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(connectivity): gate backend/node RPC checks behind BB_TEST_BACKEND_CONNECTIVITY

The connectivity suite dialed both the raw backend/node RPC (rpc_url) and the
Blockbook API for every coin. The node RPC endpoints are only routable from the
CI/CD network, so local runs failed on unreachable nodes even when Blockbook
itself was healthy.

Gate the node RPC checks behind BB_TEST_BACKEND_CONNECTIVITY: off by default
(local runs verify Blockbook reachability only), on in CI. The flag is set in
the testing.yml connectivity job and the deploy.yml post-deploy connectivity
step, forwarded into the build container by the Makefile, and exposed locally
via a --backend-connectivity flag on run-integration-tests.sh. Documented in
AGENTS.md and covered by a unit test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(connectivity): route Blockbook websocket dial through egress proxy

BlockbookHTTPIntegrationTest's HTTP client already honors the proxy via
http.ProxyFromEnvironment, but the gorilla websocket.Dialer in
BlockbookWSIntegrationTest did not, so the WS check failed to resolve the
Blockbook host from behind an egress proxy (where it is only reachable through
the proxy). Set Proxy: http.ProxyFromEnvironment on the dialer to match the
HTTP client and the OpenAPI e2e suite; a no-op when no proxy is configured.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): resolve build/deploy coin aliases against the context, not cwd

resolve_build_selection and resolve_deploy_selection normalized the "_"→"-"
coin alias with normalize_coin_name(Path.cwd(), ...), so the underscore form of
a hyphenated coin (e.g. ethereum_classic → ethereum-classic) only resolved when
the process happened to run from the repo root. Run from any other directory
(e.g. the unit tests) the alias was left unresolved and rejected as an unknown
coin.

Resolve against the already-loaded context.all_coins instead, which is derived
from the workspace the context was built from, so selection no longer depends
on the working directory. Adds a deploy-side regression test alongside the
existing build one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(integration): drop fiat-rate e2e tests for ETH testnets (no price feed)

ethereum_testnet_sepolia and ethereum_testnet_hoodi disable fiat rates in
configs/coins (fiat_rates-disabled instead of fiat_rates), because valueless
testnet ETH has no CoinGecko feed — the rate downloader never runs. The
WsGetCurrentFiatRates e2e test therefore hard-failed with "No tickers found\!",
and GetCurrentFiatRates/GetTickersList/GetMultiTickers/WsGetFiatRatesForTimestamps/
WsGetFiatRatesTickersList only ever skipped.

Remove the six fiat-dependent tests from both testnet entries; the non-fiat
GetBalanceHistory/WsGetBalanceHistory stay. Mainnet ethereum (fiat enabled) and
tron_testnet_nile (fiat enabled via mainnet TRX's CoinGecko id) keep them.

Verified: OpenAPI e2e now passes for both coins (54 ok, 4 unrelated skips, 0 fail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(e2e): cover GetContractInfoNonVaultEVM on ethereum_testnet_sepolia

Add an OpenAPI fixtures file for Sepolia with two canonical, permanently
deployed ERC20s — Chainlink LINK (0x7798…4789) and Circle USDC
(0x1c7D…7238) — and enable GetContractInfoNonVaultEVM for the coin. The test
GETs /api/v2/contract/<addr>?protocols=erc4626 and asserts the contract
resolves and is NOT mis-flagged as an ERC4626 vault (the strict opt-in gate).

Both addresses were verified indexed on the deployed Sepolia Blockbook
(correct symbol/decimals, protocols absent); e2e passes (29 ok, 1 unrelated
skip, 0 fail).

Not added for ethereum_testnet_hoodi: that testnet has no token ecosystem
indexed, so there is no stable contract to anchor a fixture. The remaining
EVM contract/protocol/ERC4626 tests still require curated on-chain vault and
holder fixtures that do not exist on these testnets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(ci): harden testnet test plumbing after review

Follow-up hardening surfaced by a deep review of the testnet test work; no
behavior change on the happy path.

- deploy_plan.build_connectivity_regex: fail closed on an empty name list. An
  empty "()" alternation matches the empty string, so `go test -run` would
  select EVERY connectivity subtest instead of none. The caller already filters
  to a non-empty set; this makes the deploy-gating helper safe on its own.
- runner_test: pin canonical_coin_name's check ordering so underscore-native
  coins (e.g. base_archive, ethereum_testnet_sepolia) are returned unchanged
  rather than rewritten to a hyphen variant — a reorder regression would
  otherwise stay green.
- config.ts: document the "disabled" stay-in-sync contract on the actual
  filtering logic (it previously lived only on the types.ts declaration) and
  explain why the explicit-OPENAPI_COINS guard is needed alongside the filter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… convention

Token transfer / token balance responses dropped the `decimals` field
whenever it was 0 (the JSON tag carried `,omitempty`), so clients could
not distinguish a genuine 0-decimal token from missing metadata and had
to guess (trezor-suite defaults to 18). See trezor#1577.

- Remove `,omitempty` from api.Token.Decimals and api.TokenTransfer.Decimals
  so the field is always present (matches the existing ContractInfoResult).
- In getContractDescriptorInfo, when a contract's metadata cannot be read
  on-chain, fall back to the coin's default decimals (18 for ERC-20)
  instead of surfacing/persisting an ambiguous 0. Genuinely 0-decimal
  tokens always carry a resolved (handled) standard, so they keep their 0.
- Mirror the always-present field into blockbook-api.ts and mark decimals
  required in openapi.yaml for Token and TokenTransfer (parity typecheck).
- Add a regression test asserting decimals is serialized even when 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add assertTokenDecimals and wire it into GetAddressTokensEVM (Token) and
GetTransactionEVMShape (TokenTransfer), making the trezor#1577
expectation explicit on top of the schema's `required: decimals`. The check
reuses already-fetched responses (no extra requests), runs on all EVM coins,
and additionally enforces a non-negative integer, which the schema does not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The REST rate limiter only wrapped routes under /api*, so the HTML
explorer pages (/address/, /xpub/, /tx/, /search/, …) bypassed it
entirely — even though they call the same expensive backend as the API
(GetAddress, GetXpubAddress). A flood of /address/<addr> requests was
neither throttled nor counted by the limiter.

Replace the /api-only allowlist with a deny-all-except-static gate
(isRateLimitedRoute): every dynamic public route under the server base
path is now limited under one shared per-client budget, and only static
assets, api-docs, the OpenAPI spec, and the WebSocket endpoint are
exempt. WebSocket must stay exempt because its handler blocks for the
whole connection lifetime and has its own limiter. New routes are
covered automatically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rage

Now that the limiter covers both the explorer UI and the REST API, the
REST_ naming is misleading. Rename throughout:

- env vars: <NET>_REST_* -> <NET>_REST_UI_* (the unrelated
  <NET>_REST_BALANCE_HISTORY_MAX_TXS is left untouched)
- Go identifiers: restAPI*/RestAPI* -> restUI*/RestUI*
- Prometheus metrics: blockbook_rest_api_* -> blockbook_rest_ui_*
- docs/env.md and Grafana panels updated accordingly

No backward-compat aliases: the limiter is unreleased (on master, not in
v0.5.0), so the old names never shipped. Existing dashboards/alerts
referencing blockbook_rest_api_* must move to blockbook_rest_ui_*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
isRateLimitedRoute exempted any path with the "api-docs" prefix, so a
request like /api-docsx bypassed the limiter and fell through to the
explorer index handler unthrottled. Match the registered routes exactly
("api-docs" and "api-docs/...") instead, mirroring the other exemptions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The limiter panels' titles, help, and metric names already moved to the
"Public HTTP" / rest_ui naming when the limiter was extended to cover the
explorer UI; their x-panel-key join keys were left as rest_api. Rename
the three limiter panels (rejections, active_ips, max_active_per_ip) to
rest_ui.* in both template.json and panels.yaml. The rest_api.requests
and rest_api.balance_history_* panels describe REST API endpoint traffic
and keep their keys. render_grafana.py --check passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reduce the default per-client REST/UI limits to clamp abusive traffic
more tightly: rate limit 600->180 req/min (3 req/s), burst 120->40,
max-concurrent 24->12. Still overridable per network via the
<NET>_REST_UI_* env vars; update docs/env.md to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
isRateLimitedRoute assumed basePath always ends in "/", but splitBinding
keeps a "-public=:port/path" binding verbatim (e.g. "/bb"). With such a
base path, TrimPrefix left a leading slash on rel ("/favicon.ico"), so the
deny-list missed and static assets, favicon, api-docs and openapi.yaml were
incorrectly rate-limited while dynamic routes stayed covered. Trim any
leading slash so the suffix matches in either binding shape, and cover the
slash-less base path in TestRestUIRouteMatching.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The defaults-lowering commit updated the code and docs/env.md to 180/40/12
but not the Grafana panel descriptions, which still told operators the
budget was 600/min, burst 120, concurrency cap 24. render_grafana.py --check
does not validate description prose, so the drift went unnoticed. Sync the
rest_ui.rejections and rest_ui.max_active_per_ip descriptions to 180/40/12.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The RestAPI->RestUI field rename left the four limiter fields one space
short of the struct's gofmt tag-alignment column, so `gofmt -l` flagged the
file. Re-align; whitespace only, no behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The REST/UI limiter deny-list also exempts /test-websocket.html, but the
exemption list omitted it. Add it. Also reword the "Despite the REST_
prefix" caveat, which no longer fits now that the variables are named
REST_UI_* and already advertise UI coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rename of the env vars to REST_UI_* and the lowered 180/40/12 defaults
were verified only by the build, not by any assertion. Add a
readRestUILimiterConfig test that locks the lowered defaults, checks each
REST_UI_* override, and asserts the zero-burst validation error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(syscoin): port Syscoin support to latest upstream

Reapply Syscoin SPT parsing, indexing, API, explorer, packaging, and test fixtures on top of current upstream Blockbook so the fork can review Syscoin-specific changes separately from the main replacement.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): forward mempool asset and send option wrappers

Keep Syscoin asset mempool lookups indexed through BaseMempool and forward both asset lookup and optional sendrawtransaction parameters through upstream metrics wrappers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): stabilize asset paging and block hash lookups

Sort Syscoin asset search results before paging and preserve upstream header lookup behavior when blocks are requested by hash without a known height.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): verify testnet backend artifacts

Add the Syscoin 5.1 release checksum signature metadata to the testnet backend config so the upstream artifact lint accepts both default and arm64 downloads.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(syscoin): inherit upstream block lookup

Remove the Syscoin GetBlock override now that the embedded BitcoinRPC already uses the Syscoin parser and upstream header lookup behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): preserve asset metadata in mempool filters

Carry indexed SPT asset metadata through mempool input lookups and mark asset-mask filtered histories as unknown-sized for paging.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): address latest asset and proof review issues

Return SPV proof payloads without double encoding, preserve asset masks in explorer paging, treat asset-mask address histories as filtered, and keep registry precision for ERC20 assets.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): return SPV proof as raw JSON

Carry syscoingetspvproof results as json.RawMessage so object proofs are returned without string escaping.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): keep SPT ERC20 display precision

Restore 8-decimal display precision for ERC20-backed Syscoin assets because SPT amounts are indexed as Syscoin CAmount values.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): retry fallback assets and expose mempool input metadata

Retry NEVM metadata when cached asset placeholders are encountered and include SPT input metadata in mempool websocket transaction conversion.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): preserve parsed block parents and cap asset pages

Preserve previous block hashes for Syscoin raw block parsing and keep asset history responses bounded when mempool rows are prepended.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): reject unknown NEVM assets and preserve asset masks

Avoid caching fabricated NEVM asset metadata for unsupported registry entries and keep Syscoin assetMask filters on address pagination links.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): normalize asset value strings and mempool deltas

Keep asset valueStr numeric-only and compute unconfirmed asset balances from both mempool outputs and inputs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): expose asset symbols for tx details

Keep assetInfo valueStr numeric while exposing asset symbols separately for transaction detail display.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): prioritize exact asset search and preserve paging

Resolve exact numeric asset searches before fuzzy matches and page asset histories over mempool plus confirmed transactions without skipping confirmed rows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): handle asset search and paging edge cases

Resolve numeric asset GUID searches before block-height redirects and avoid confirmed asset history fetches when a page is filled by mempool entries.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): normalize template shortcut checks

Use the shared Syscoin shortcut helper in templates so testnet tSYS renders Syscoin-specific UI controls.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): bound NEVM calls and avoid asset cache pollution

Apply configured RPC timeouts to NEVM metadata calls and use non-caching RocksDB read options for full asset cache scans.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): record NEVM metadata errors in metrics

Pass FetchNEVMAssetDetails errors through the metrics wrapper so failed metadata RPC calls are observable.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): assign unique testnet ports

Move Syscoin testnet to an unused port block so it no longer collides with bgold testnet services.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): avoid NEVM port collision

Move Syscoin's managed NEVM HTTP endpoint off Tron's shared port and size the asset transaction-count VLQ buffer for the full encoded range.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): add lowercase asset tx count alias

Expose lowercase txs on asset-search rows while preserving the legacy Txs field for existing Syscoin clients, and document the intentional 8-decimal UTXO asset formatting.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): use lowercase asset search tx count

Keep asset-search transaction count consistent with the rest of the API by exposing only the lowercase txs field.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): propagate asset parse failures

Return SPT allocation decode errors from Syscoin transaction and block parsing so malformed asset transactions cannot be indexed without AssetInfo.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): reject malformed asset payloads

Validate SPT OP_RETURN pushdata lengths and allocation output indexes so malformed asset transactions return parser errors instead of panicking.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syscoin): omit SYSX zero contract

Keep the built-in SYSX asset contract empty so native SYSX does not expose or link to the zero NEVM address while preserving canonical metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jagdeep sidhu <sidhujag@syscoin.org>
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(syscoin): restore explorer UX after upstream merge

Preserve Syscoin explorer surfaces on the upstream-latest base and keep shared templates guarded so non-Syscoin explorers continue to render correctly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update public.go

---------

Co-authored-by: jagdeep sidhu <sidhujag@syscoin.org>
Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve upstream-latest ancestry while replacing master contents with the upstream-latest tree so stale master-only files are removed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sidhujag sidhujag merged commit 20461f4 into master Jun 30, 2026
1 of 2 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dfe2a5a69a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .gitlab-ci.yml
@@ -1,193 +0,0 @@
stages:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve upstream-latest as an actual parent

When this PR is merged with the intent of making master no longer behind upstream-latest, this commit still will not carry that ancestry: git show --pretty=raw 50158194... shows only parent f5dfc9be..., with no upstream-latest/e73682ea... parent. The file deletions make the tree match upstream, but a GitHub merge commit of this branch would have parents master and this single-parent commit, so upstream-latest remains outside the ancestry; the branch needs to contain the actual merge commit before merging.

Useful? React with 👍 / 👎.

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.

8 participants