You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4b96844
Browse filesBrowse the repository at this point in the historyBrowse files
fix(kotlin-sdk): review round — the reconcile mutates nothing it cannot prove
thepastaclaw review round on dashpay#4439, all four blockers:
- The spent-flip is demoted to LOG-ONLY (wouldFlipSpent): the engine's
spent set records every input of every recorded transaction including
MEMPOOL spends, with no context — persisting the flip would settle an
unconfirmed spend, contradicting this handler's own in-block gating.
Re-arm as a mutation only when the engine exports spends with context.
- upsertUtxoRow reports whether it wrote: a globally-swept-parent refusal
is now visible to the reconcile (skippedSwept), which no longer counts
phantom heals nor flags netAmounts for rows that were never inserted.
- The netAmount repair is demoted to LOG-ONLY (netAmountSuspects): a
corrective record callback can land while its TXO delivery races this
sweep, and blind addition double-credits. The event pipeline owns net
correctness; the reconcile reports the suspicion.
- The restore-time pool repair announces every pool it cannot repair
(DashPay contact pools have no public key source by design and re-derive
through DashPay sync; hardened pools cannot be publicly derived).
Plus the review suggestions: contact-row exclusion now resolves ownership
through coreAddressId -> core_addresses.accountId (production rows leave
txos.accountId null, so the accountId-only check was ineffective), the
neither-inventory log names the finalized-drop ambiguity, and the JNI
spent-outpoint export uses the canonical OutPointFFI conversion.
The reconcile is now fully observe-and-heal-forward: its only mutation is
inserting provably-owned engine UTXOs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/persistence/PlatformWalletPersistenceHandler.kt
+88-39Lines changed: 88 additions & 39 deletions
Original file line number
Diff line number
Diff line change
@@ -1075,7 +1075,7 @@ class PlatformWalletPersistenceHandler(
1075
1075
isConfirmed:Boolean,
1076
1076
isInstantLocked:Boolean,
1077
1077
isLocked:Boolean,
1078
-
) {
1078
+
): Boolean {
1079
1079
val outpoint = makeOutpoint(txid, vout)
1080
1080
val parentTx = db.transactionDao().getByTxid(txid)
1081
1081
// A globally-swept parent is a transaction Rust has already
@@ -1099,7 +1099,7 @@ class PlatformWalletPersistenceHandler(
1099
1099
// defensive here is correct: there is no record in flight to
1100
1100
// attribute a resurrected output to. See
1101
1101
// TransactionEntity.isGloballySwept.
1102
-
if (parentTx?.isGloballySwept ==true) return
1102
+
if (parentTx?.isGloballySwept ==true) returnfalse
1103
1103
// Ensure a parent transaction row exists (stub if missing, so
1104
1104
// the TXO FK holds; the real tx upsert overwrites it later).
1105
1105
if (parentTx ==null) {
@@ -1209,6 +1209,7 @@ class PlatformWalletPersistenceHandler(
1209
1209
}
1210
1210
for (p in pending) db.documentDao().deletePendingInput(p)
1211
1211
}
1212
+
returntrue
1212
1213
}
1213
1214
1214
1215
/**
@@ -1222,15 +1223,26 @@ class PlatformWalletPersistenceHandler(
1222
1223
valengineUtxos:Int,
1223
1224
valinserted:Int,
1224
1225
valinsertedDuffs:Long,
1225
-
valnetAmountRepairs:Int,
1226
+
/** Healed TXOs whose pre-existing record's netAmount MAY be short by
1227
+
* the healed amount. LOG-ONLY: the record can already carry the
1228
+
* corrected net (a corrective callback racing this sweep), and
1229
+
* blind addition double-credits. The event pipeline owns net
1230
+
* correctness. */
1231
+
valnetAmountSuspects:Int,
1226
1232
valskippedImmature:Int,
1227
1233
valskippedNoAddress:Int,
1228
1234
valaccountErrors:Int,
1229
-
/** Store rows marked unspent whose outpoint the engine knows was
1230
-
* spent — the lost-spend-update class (dashpay/platform#4425);
1231
-
* flipped to spent in place. */
1232
-
valflippedSpent:Int = 0,
1233
-
valflippedSpentDuffs:Long = 0,
1235
+
/** Store rows marked unspent whose outpoint the engine records as
1236
+
* spent — the lost-spend-update class (dashpay/platform#4425).
1237
+
* LOG-ONLY: the engine's spent set includes mempool spends with no
1238
+
* context, so flipping would persist an unconfirmed spend as
1239
+
* settled. */
1240
+
valwouldFlipSpent:Int = 0,
1241
+
valwouldFlipSpentDuffs:Long = 0,
1242
+
/** Engine UTXOs whose insert the shared discipline refused (their
1243
+
* parent transaction is globally swept) — excluded from
1244
+
* [inserted], never netAmount-affecting. */
1245
+
valskippedSwept:Int = 0,
1234
1246
/** Store rows marked unspent that the engine has in NEITHER
0 commit comments