Skip to content

Release v0.11.0 - #11

Merged
jdogresorg merged 11 commits into
masterfrom
release/v0.11.0
Aug 26, 2026
Merged

Release v0.11.0#11
jdogresorg merged 11 commits into
masterfrom
release/v0.11.0

Conversation

@jdogresorg

Copy link
Copy Markdown
Contributor

Release v0.11.0 for xchain-decoder. The diff is the release: the version bump, this repo's changelog entry, and any release-time fields the ceremony sets.

Changelog entry

Added

  • The API serves a getmempool method so remote explorers can read the live mempool, including the node's total unconfirmed count.
  • Mempool rows record when this decoder first observed them, applied as an automatic additive migration.

Changed

  • Updated the BTC mainnet validator reward pool address.
  • Moved the BTC, LTC and DOGE testnet genesis start points forward to just under the live chain tip and regenerated the consensus pin, so the public testnet launches with no pre-announcement test history.

Fixed

  • The migrations this service asserts at startup are now declared to the deploy tool, and one whose end state already holds is recorded as applied without re-running its statement.
  • Cumulative log-shipper totals are now reported as counters instead of gauges, so rate queries over them return correct values instead of being undefined.
  • Mempool counts and feeds now include only action-carrying rows, instead of every transaction the node's mempool holds.
  • A malformed or blank RPC timeout environment variable no longer silently disables the request timeout, which could leave a stalled node connection hanging indefinitely.
  • RPC error responses from newer node software that reply with HTTP 200 (Bitcoin Core 28 and later) are now classified and retried the same as other RPC failures.

Bitcoin, Litecoin, and Dogecoin are where the platform runs today, not the
definition of it; the README says so where it names them.
The mempool table is deliberately excluded from replication (it is
node-local, non-deterministic observation state), so an explorer serving
from synced replicas has no database path to pending actions. Add a
getmempool JSON-RPC method as that path: it returns the node's total
mempool tx count (snapshotted each poll cycle), the count of
action-carrying rows, and a bounded 500-row window of tx_hash / source /
data / first_seen. The method is TTL-cached so an unauthenticated
request burst cannot amplify into pooled-connection contention against
the block loop.

Pending rows also gain a first_seen timestamp (server-side insert
default; automatic additive migration) so clients can show when a
pending action was first observed.
The mempool table holds a row for EVERY transaction the decoder observes
in its node's mempool, not just ones carrying an action: the shared
storage gate blanks the payload to an empty string when a money-bearing
transaction's action was invalid or unknown, which on a public chain is
nearly all of them (measured on testnet: 32 of 32 rows).

So the unfiltered count getmempool reported was the size of the whole
node mempool, which a consumer publishing it as the pending-action count
turns into every unrelated payment on the chain reading as a pending
action. The unfiltered row window had a worse failure: on a busy chain
all 500 slots fill with actionless rows, so the feed renders empty while
real pending actions sit deeper in the table.

Both now filter to rows that carry a payload, matching what consumers
already keep after decoding.
This service asserts three schema shapes at startup and crash-loops when
one is unmet, but none of those migrations said so in a way the deploy
tool could read, so a fleet upgrade discovered the requirement as an
outage instead of a refusal.

Each of the three now carries the deploy-precondition tag in its header,
and a registry names the assertion, the file and the symptom so the
error an operator reads points at the exact file. A parity test keeps
the halves in step: every registered entry must exist, be gated, and
carry the tag.

Tagging alone would have refused every database built fresh from the
schema files, which satisfies all three by construction while recording
none of them. The two shape preconditions that were missing are added
alongside, so such a database records what is already true instead of
being turned away.

The tags are header comments; no executable statement changes. The
recorded checksums move with them, so the immutability guard heals
forward rather than tripping fleet-wide.
The block-loop reads and the operator log line spelled wire field positions as
bare numeric literals beside the indexer-derived constants they must track.
…fixture

The fee-destination comment in the vendored coin bundles said the override
was env-overridable after it had been restricted to regtest. Those three files
are vendored byte-identically across the fleet behind conformance guards, so the
correction is propagated rather than applied in one place.

Cumulative log-shipper totals were registered as gauges, so a _total-suffixed
series read to a scraper as a resettable level and rate() over it was undefined.
They are counters now, written through the monotonic setter that refuses a
backwards step; buffer depth is a real level and stays a gauge. Vendored through
the observability sync script, not hand-edited.

The shared roundtrip conformance fixture pinned every carrier lane except the
taproot envelope, which was the newest and the only unpinned one.
@jdogresorg
jdogresorg merged commit 909672e into master Aug 26, 2026
8 checks passed
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