Repository navigation
release: 0.6.0, the tracker hosted (the served poll gone, the spender bound, the gift claim the wallet's own); the toolbox 0.6.0 - #11
Merged
Conversation
The manifest and the lock only. The tracker is at Calhooon/bsv-tracker main 99a9ae9, not yet on crates.io; the CLI takes it from the local clone until it publishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tes (E1) A provider's "spent by X" is a word. Before X is asked for a proof and before `confirmed`, X's bytes are read through `get_raw_tx`: they must hash to X and hold the outpoint among their inputs. Bytes that could not be read leave `Unknown` (never released); bytes that spend something else mean the provider named no spender, and the probe falls through to the unspent question. Witness: a_named_spender_is_bound_to_the_outpoint_by_its_own_bytes. Red at 9235de5: SpentBy { confirmed: true } for a mined transaction that spends another outpoint. Green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l is gone (E3) The served loop asked WhatsOnChain and Bitails every 60 s about every unproven transaction. The answer it waited for was "mined", and that is a proof. The loop now runs the transaction tracker's pass in its place and asks no chain index. The host (src/tracker_host.rs) supplies the tracker's four things: Headers (a snapshot of the header service's tip and the headers a pass names, failing closed), ProofFetcher (get_merkle_path for one named transaction), HintSource (the wallet's broadcast memory rows, each word fed once) and Clock. The state is in the wallet's own database (tracker_states): the hints heard and the raw merkle path, never a trusted word; a stored path is checked again against the active header every time its row is read. A checked proof is handed to the wallet's storage through its one proof funnel (ingest_merkle_proof). A pass tracks the wallet's own unproven transactions, feeds the new hints, ticks the clock, and runs the re-asks that are due: one proof request for one transaction, the pause doubling between two asks (TRACKER_AGE_SECS, default 600; TRACKER_MAX_ASKS, default 20). A mined row is read again only when a header at or below its height moved (the last twelve tips are kept) or when the spend guard is run for it. New: `bsv-wallet tracker-tick`, one pass. `serve` and `serve-fleet` run the same pass every 60 s, then the sweep of the verdicts already in storage and the locked-input re-checks. No longer routine: retiring a transaction because the chain indexes do not know it. `reconcile-broadcasts` (by hand) is the one caller left of that probe. BROADCAST_RECONCILE_MAX_PROBES and BROADCAST_RECONCILE_MAX_LOCKED_CHECKS are no longer read by the served loop. Witness: the_served_pass_asks_for_a_proof_and_never_a_chain_index. Red at 9235de5: the served pass requested /tx/hash/{txid} of the chain index. Green, with four tests of the host, the tracker README's wallet spend guard run as the host among them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sks at the lock time (E2) A forced claim went to the wallet's broadcasters, and a broadcaster that called it not final (ARC and Arcade's 476) made the command fail with nothing kept. The claim is a transaction this wallet built, so the tracker now holds it from the moment it is handed over, and the command prints the tracker's word in place of an explorer link. - Accepted: the acceptance is a hint, the word is `announced`. Before the lock time no proof can exist, so nothing is asked about it until then. - Called not final, with --force, before the lock time: not a failure. The refusal is a hint (the word stays `built`, with a re-ask); the claim is kept with its BEEF and handed to the broadcasters again at the lock time by the tracker's pass (`serve`'s loop, or `tracker-tick`). "Not final" again waits one pause (the node reads the median time past, behind our clock), sixteen times at most. - Any other refusal, or "not final" without --force or past the lock time: the error it was, saying what they said. gift-claim's JSON gains word, reask, heldUntil and notFinal; broadcast is null when no broadcaster took the claim. Witness: a_forced_claim_called_not_final_is_tracked_and_re_asked_at_the_lock_time. Red at 980b1e9: "broadcast rejected by every broadcaster (Arcade: 476 non-final)". Green, with the host's own test of the re-announce. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The gift flow sent the recipient to `bsv-wallet sync`, an address scan of the chain, to learn that a claim this wallet had just made had landed. The wallet's storage is the verdict for its own actions: gift-claim now internalizes the claim from the BEEF it already holds (the deposit with its checked proof, and the claim), naming every output that pays the deposit script as a payment to the deposit key. The coins are spendable balance the moment a broadcaster takes the claim. A claim held as not final (--force before the lock time) is not out, so it is not recorded then: its internalize arguments are kept with its BEEF, and the caller that holds the wallet (`serve`'s loop, `tracker-tick`) records it when a re-announce is accepted. If the wallet cannot record the claim (a deposit whose proof no courier delivered), the claim is still out; the command says so and names `bsv-wallet receive <claim txid>`, by txid, never the scan. gift-claim's JSON gains recorded and recordError. gift-inspect, the deposit key's doc and GIFT.md no longer name `sync`; GIFT.md's funding step names `receive <txid>`. Witness: gift_claim_records_its_own_claim_and_the_flow_names_no_chain_scan. Red at 8243dfd: 0 satoshis in the wallet's storage after the claim (5844 expected). Green, with the held claim's test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… bound, the gift claim the wallet's own) The CLI hosts the transaction tracker (bsv-tracker 0.1.0). Needs bsv-wallet-toolbox-rs 0.5.0, as 0.5.0 did. 1. The spend probe binds a named spender to the outpoint by the spender's own bytes before it asks for the proof and before `confirmed` (cleanup-abandoned, reconcile-outputs, the daemon's sweep, sync --reconcile-spent). A provider naming some other mined transaction no longer relinquishes an output. 2. `serve` and `serve-fleet` no longer ask WhatsOnChain and Bitails every 60 s about every unproven transaction. The loop runs the tracker's pass: each of the wallet's unproven transactions holds a word; a broadcaster's word is a hint; a merkle proof is asked for one named transaction when a hint disagrees or its age is due, and only a proof checked against the header service writes `mined`. New command: `bsv-wallet tracker-tick`. New settings: TRACKER_AGE_SECS (600), TRACKER_MAX_ASKS (20). 3. `gift-claim --force`: a broadcaster calling the claim not final is not a failure. The claim is kept and announced again at the lock time by the tracker's pass. The command prints the tracker's word. 4. `gift-claim` records its own claim in the wallet. The gift flow no longer names `sync`. What an operator sees: - The wallet database gains two tables, tracker_states and tracker_meta, created on the first pass. 0.5.0 ignores them. - `serve` no longer retires a transaction because the chain indexes do not know it. `bsv-wallet reconcile-broadcasts` does that, by hand; each pass lists the transactions it asked a proof for and got none. - BROADCAST_RECONCILE_MAX_PROBES and BROADCAST_RECONCILE_MAX_LOCKED_CHECKS are no longer read by the served loop (the sweep re-checks 20 locked inputs a pass, the default it had). - gift-claim's JSON: `broadcast` is null when no broadcaster took the claim; new fields word, reask, heldUntil, notFinal, recorded, recordError. Rollback: install 0.5.0; the two tables are left unread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… answer a hint): the probe reads UnspentHint, a SpentHint names no spender and is left to the cadence Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
The owner's calls of 2026-10-09 (bsv-stack-lean docs/RULINGS-2026-10-09.md, E1 to E4, decided by the captain after the north star): the CLI hosts bsv-tracker 0.1.0 from crates.io with the four host things, the state in the wallet database and
tracker-tick; the served loop's 60 s chain-index probe is gone; a spender named by a provider is bound to the outpoint by its own bytes before the proof;gift-claim --forceholds a not-final claim as the tracker's and re-asks at the lock time;gift-claimrecords its own claim and the gift flow names no chain scan. The toolbox pin moves to 0.6.0 (a stranger's spend only by proof; an unspent answer a hint): the probe readsUnspentHint, aSpentHintnames no spender and is left to the cadence. 323 tests, clippy, fmt at f4b4273 on the captain's host (bsv-stack-lean docs/p0/cli-0.6.0-tracker.md).serveno longer retires a transaction a broadcaster accepted but the network never showed;reconcile-broadcastsby hand stays the explicit act.🤖 Generated with Claude Code