Repository navigation
fix: retain prepared transaction fees - #1459
ben-kaufman wants to merge 2 commits into
Conversation
|
Regtest APKDownload bitkit-dev-debug universal APK (expires in 30 days). |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Persists each prepared candidate's exact mining fee in the attempt record before dispatch, and uses only the winner's own fee when local follow-up runs ahead of transaction history. Reviewed 10e0065, full tier on the changed paths. Not built here: Bitkit Android reviews are reasoned from the code and from CI.
What I checked, and 5 candidates I ruled out
Read: the diff whole; in OnchainSendAttemptStore.kt, retainPreparedReceipt, discardUnsubmittedRetryCandidate, the broadcast-failure reset, restoreActive, load; in LightningRepo.kt, finishOnchainSendLocally and winningCandidateFee; in LightningService.kt, prepareOnchainSend and observedOriginalSendFee; ActiveOnchainAttemptBackup.from/restored.
Call sites traced: the only OnchainPreparedReceipt producer (prepareOnchainSend, fee from prepared.miningFeeSats() of the same signed tx as txid); every write to candidateTxids.
CI: build (assembleDevDebug + testDevDebugUnitTest), lint, detekt, build-local green; e2e-tests-local shards still pending at review time.
Ruled out
- Wrong candidate's fee: the map is keyed by the lowercased txid of the receipt that produced it, and lookup uses
attempt.txid, so a successor never reads the original's entry (the existing successor test now asserts this with an original-only entry). load()invariant tripping on old or reset records: every path that drops a txid fromcandidateTxids(discard, broadcast-failure reset) drops it fromcandidateMiningFeestoo, and records without the field decode toemptyMap().- Restore replay wiping local fees:
restoreActivenormalises the field before comparing and persistsexisting, so an identical replay keeps local evidence; backup export never carries the field. - Fee overwriting on retry of the same txid:
retainedMiningFeesrefuses a differing fee for a known txid before persisting. - Changed authorization equality:
authorizeOnchainRecoveryandonRecoveredTransfercompare whole attempts, but the new field changes in the same write ascandidateTxids/candidateFeeRates, which those checks already tolerate.
Merge confidence: 4/5, no findings, but the changed files were read in their touched regions rather than whole and the e2e shards had not finished.
This PR retains each prepared transaction's exact mining fee before broadcast so an accepted payment can complete local bookkeeping while transaction history catches up.
iOS already retained ordinary-send fees; its narrower replacement-recovery counterpart is synonymdev/bitkit-ios#915.
Description
Out of Scope
Design
N/A - no UI changes.
Preview
N/A - recovery bookkeeping only.
QA Notes
Journeys
N/A - not drivable; see Manual Tests.
Manual Tests
prepared-fee-recovery.md: delay transaction-history details after Accepted, restart after receipt persistence, and exercise replacement/original winners -> exact winner fee and one local activity/proof, with no extra send; native history fault injection is not in Capabilities.Automated Checks
OnchainSendAttemptStoreTest.kt- persisted original/replacement fees survive file/fsync reopen; conflicting fees fail closed; local backup replay preserves private evidence.LightningRepoTest.kt- accepted winners use only their own fee, including zero; Unknown and mismatched shop requests do not complete.OnchainSendCoordinatorTest.kt- receipt fees are durable before dispatch, failed storage prevents dispatch, and discarded candidates lose only their own metadata.LightningRepoTest.kt- a missing successor fee never borrows the original candidate's fee and still uses the existing history fallback.Final local validation on master
3cac93b0: compilation and 3,948 tests across 222 suites passed. Complete format/Detekt reports contain the same 1,981 verified baseline findings, with zero introduced findings or suppressions; all 31 test compiler diagnostics match the base. Three tests added, none removed. Repository-native review, production-polish sweep and a fresh frozen correctness/quality gate completed with no outstanding findings.Controlled device/payment checks above remain unrun. The isolated earlier Accepted-payment fixture was preserved and not resumed; no new payment, funding or broadcast was performed for this fix.