Skip to content

bench 308 published a market Firo has not had, and both its columns were blank - #3314

Merged
Flotapponnier merged 2 commits into
devfrom
fix/privacy-coin-books-gauges
Oct 27, 2026
Merged

Flotapponnier merged 2 commits into
devfrom
fix/privacy-coin-books-gauges

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Four defects on bench 308, each one measured against the live feeds.

A coin whose makers left kept its row

A Prometheus gauge that is never Set keeps its last value for as long as the process lives. probeBasicSwap published only the coins it found on the book, so a coin that disappears from the feed never gets a new value and keeps republishing the market it used to have.

Measured 2026-10-27: privacy_book_maker_count{coin="FIRO"} has been flat at 1 for 24 h (changes(...[24h]) = 0) while the BasicSwap feed carries zero Firo offers, expired or otherwise. The abstract already promised the opposite:

Expired offers are excluded. The feeds keep them in the list, and counting them would let a coin whose last maker left months ago keep a row that looks like a market.

The expiry filter does its job on offers; nothing did it on the gauge. Every coin in the cohort is now published every tick, zero included. zero_is_a_value: true ships with it, otherwise the honest 0 deletes the row instead of showing it, and a coin whose market left is the most informative row this board has.

One guard kept: an empty offer list is a feed failure, not an empty market, and still publishes nothing.

The Pairs column over-counted

The feed carries an offer as an ordered (coin_from, coin_to) pair, and the key was from + "/" + to, so a market listed in both directions counted twice. Measured on the live book:

coin published real markets
XMR 8 5
DASH 3 2
WOW 5 4

The key is now undirected and the column is named Markets, which is what it counts.

Both companion panels rendered empty

load.ts builds a panel query as `${panel.label_key}="${p.slug}"` with no normalisation. The gauges were labelled XMR, PART_BLIND; the rows are xmr, part-blind. Nothing matched, values came back {} for both panels, and no error was raised anywhere, while the subtitle promised "the offers and pairs behind the count". The harness now labels by row slug and the provider queries move with it.

sample_size was not a sample count

It was sum(privacy_book_live_offers{...}), so PIVX showed "3 samples" because PIVX has three offers. It is now max(count_over_time(privacy_book_maker_count{...}[24h])), the number of scrapes behind the row.

Two additions that follow

  • Coins on offer column, from the privacy_book_size_offered gauge the harness already collected and the board never showed. The second finding claims one maker can offer thousands of coins; now there is a column where a reader can check it.
  • Dedupe by peerId on the Monero maker directory. 9 entries, 9 distinct peers today, so this changes no number; the headline column must not be able to count one participant twice.

Tests

basicswap_test.go covers the undirected key, reciprocal offers, an expired offer, the zero-fold for every cohort coin, and which side the size comes from. Each gate was proved to pull: with the old behaviour reinstated, the direction and reciprocal tests fail and the expired-offer test dies on the nil entry that is the frozen-gauge path.

Gates: go build ./... && go vet ./... && go test ./... ok, pnpm validate 257 specs valid, tsc --noEmit clean, bun test src/ 731 pass 0 fail.

Deploy order

The harness must ship before the worker rebuild: the spec now selects coin="xmr" and that series does not exist until the new binary runs. In between, the bench fails quorum and keeps its previous render, which is the intended behaviour of that guard.

Flotapponnier and others added 2 commits October 27, 2026 16:16
All three providers on privacy-round-trip query asset="ZEC.ZEC", so the
seo_title "Zcash and Dash in and out" named an asset the table does not
carry. The harness does measure Dash, but only on Maya: THORChain and
NEAR Intents do not quote it, and this board's rows are rails, so a Dash
row would be one rail wide. The title now says what the board shows and a
methodology bullet says why it is one asset wide, pointing at the exit
cost board for the asset comparison.

307's title was correct but read as arbitrary: nothing on the page said
why Zcash. It is the only asset measured that HAS a shielded address
format, Monero being private by default and Dash offering optional mixing
over ordinary addresses. Added as a bullet.

THORChain shipped without a mark and rendered as a letter tile. The logo
is the 180x180 icon thorchain.org declares in its own head, shape checked
before it was kept.

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

Four defects, each measured against the live feeds rather than read off the
code.

A gauge that is never Set keeps its last value for as long as the process
lives. probeBasicSwap only published the coins it found on the book, so a
coin whose makers left kept republishing the market it used to have. Firo
sat at one maker for a full day on 2026-10-27 while the feed carried no Firo
offer at all, which is the exact row the abstract says this bench refuses.
Every coin in the cohort is now published every tick, zero included, and
zero_is_a_value goes with it so the row reads 0 instead of being deleted.

The Pairs column over-counted. The feed carries an offer as an ordered pair,
so XMR->BTC and BTC->XMR were two "distinct pairs" for one market: Monero
published 8 where the book held 5, Dash 3 where it held 2, Wownero 5 where
it held 4. The key is now undirected and the column is called Markets.

Both companion panels rendered empty. A panel is queried as
`<metric>{coin="<provider slug>"}` with no normalisation, and the gauges
were labelled XMR while the rows are called xmr, so nothing matched and
nothing said so. The harness now labels by slug and the provider queries
follow.

sample_size was the live offer count, which put "3 samples" under PIVX
because PIVX has three offers. It is now the number of scrapes behind the
row.

Two additions that follow from the above: a Coins on offer column, because
the findings already claim one maker can offer thousands and no column
showed it, and a dedupe by peerId on the Monero maker directory, which has
no duplicates today and no guard against one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Flotapponnier
Flotapponnier merged commit a705fe0 into dev Oct 27, 2026
2 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