Spike: read pending balance from the node instead of deriving it - #301
Closed
droplister wants to merge 1 commit into
Closed
Spike: read pending balance from the node instead of deriving it#301droplister wants to merge 1 commit into
droplister wants to merge 1 commit into
Conversation
A spike into what @davesta hit: mint 400,000 STARMONEY for 4 XCP, and the 4 XCP is still sitting in your balance looking spendable until the mint confirms. Compose a DEX order against the same coins in the meantime and whichever confirms second fails. The thing not to do here is re-derive Counterparty's debit rules in the wallet. Which message types debit what, in what order, under which activations, is consensus logic; a second implementation of it would be wrong eventually and wrong silently. It turns out not to be necessary: core parses mempool transactions and emits the same DEBIT and CREDIT events it emits for confirmed ones, with action/calling_function naming the reason. So the wallet asks rather than derives, and a fairmint's XCP debit arrives already labelled. Verified against a live node and against core's source: - /v2/addresses/mempool returns those events per address. Confirmed live: a pending issuance shows its CREDIT of the new asset and its DEBIT of the XCP fee, both with readable reasons. - Double counting is core's problem and core handles it. When a block is parsed, mempool rows for the transactions it contained are deleted in the same database transaction that marks the block parsed, specifically so an API reader cannot see a transaction as both confirmed and pending. There is no window to defend against. - That endpoint matches addresses with SQL LIKE against a joined column, so its results are a superset. Every event is filtered on its own params.address here; without that a neighbour's debit could be subtracted from your balance. - Quantities are unsigned 64-bit and stay bigint throughout. Rounding one through a double is the precise failure this exists to prevent. Two display decisions are baked in and are the part worth arguing with. The confirmed balance is never adjusted -- spendable is a separate figure -- because a headline number that quietly changes meaning is its own defect. And pending debits exceeding the confirmed balance is reported as a disagreement rather than rendered as a negative: the ledger says it cannot happen, so seeing it means the two reads disagree, and a confident negative would be a lie. Pure and tested without a browser; no UI yet, deliberately. Claude-Session: https://claude.ai/code/session_01QJS9Bj6uAMoYPATvfr6GZ1
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Research spike into @davesta's STARMONEY report. No UI yet — the finding is the deliverable, and the display decisions are the part worth arguing with before anything gets drawn.
The good news: we don't have to derive this
My worry was that computing "what's committed but not yet debited" means re-implementing Counterparty's debit rules in the wallet — which message types debit what, in what order, under which activations. That's consensus logic, and a second copy of it would be wrong eventually and wrong silently.
It isn't necessary. Core parses mempool transactions and emits the same
DEBIT/CREDITevents it emits for confirmed ones, withaction/calling_functionnaming the reason. The wallet asks instead of deriving.Verified live — a pending issuance returns its
CREDITof the new asset and itsDEBITof the XCP fee, both labelled. And a fairmint debits XCP with an action string (fairmint.py:287), so davesta's exact case arrives pre-explained.Three things I checked because they'd have sunk it
Double counting. I expected a race between "confirmed in a block" and "still in mempool". Core closes it: mempool rows for a block's transactions are deleted in the same database transaction that marks the block parsed, with a comment saying that's exactly so an API reader can't observe both. Nothing to defend against.
Address matching.
/v2/addresses/mempoolmatches with SQLLIKE '%address%'against a joined column, so results are a superset. Every event is filtered on its ownparams.addresshere — without that, a neighbour's debit could be subtracted from your balance.64-bit exactness. Quantities stay
bigintend to end. Rounding one through a double is the precise failure this exists to prevent.What it can't do
It only sees what the queried node has in its mempool. Point the wallet at a node that never saw your broadcast and it shows nothing pending. That's a floor on any client-side answer, and it's why the UI wording should describe what's known rather than assert what's spendable.
Two display decisions baked in
The confirmed balance is never adjusted.
spendableis a separate figure. A headline number that quietly changes meaning is its own defect — read "4 XCP", then later "0 XCP", same label, two different claims.Pending debits exceeding the confirmed balance is reported as a disagreement, not rendered. The ledger says it can't happen, so seeing it means the two reads disagree (mid-reorg, stale balance). A confident negative would be a lie.
One correction to the original feedback
davesta asked for escrow display on DEX orders too. That's already correct behaviour — an order debits
give_quantityat parse time with action"open order"(order.py:439), so a confirmed open order's funds are already out of your balance. The gap there isn't accounting, it's that nothing tells you why your XCP dropped or that cancelling returns it. Different feature.Verification
19 tests on the pure module; 4406 unit tests pass overall;
tscandbiomeclean. Live-checked against api.counterparty.io.https://claude.ai/code/session_01QJS9Bj6uAMoYPATvfr6GZ1