Skip to content

Conversation

@darioAnongba
Copy link
Contributor

@darioAnongba darioAnongba commented Oct 1, 2025

Garbage collect the residue orphaned UTXOs when creating transactions. Orphaned UTXOs occur when creating tombstones or full burns.
Currently, these UTXOs accumulate in the DB and are never cleaned. This PR introduces a garbage collection mechanism to collect these UTXOs and use them as inputs of transactions initiated by tapd:

  • Transfers
  • Burns

The PR adds a new swept flag to the managed_utxo table because UTXOs are not removed from the table when spent. This flag is also returned by the ListUtxos RPC endpoint.

The mechanism preserves the liveness and safety properties, ensuring that zero-value UTXOs can never accumulate in the DB. Adding garbage collection to Mint transactions is not necessary to ensure these properties.

Fixes #514

Note to reviewers

  1. UTXO meaning unspent, keeping the spent outputs in a table called manage_utxos seems like a contradiction, same logic applies for the need of a swept flag in that table. We should either rename the table or store spent utxos somewhere else?

@darioAnongba darioAnongba self-assigned this Oct 1, 2025
@coveralls
Copy link

coveralls commented Oct 1, 2025

Pull Request Test Coverage Report for Build 19575345571

Details

  • 293 of 382 (76.7%) changed or added relevant lines in 16 files are covered.
  • 388 unchanged lines in 29 files lost coverage.
  • Overall coverage increased (+6.7%) to 56.271%

Changes Missing Coverage Covered Lines Changed/Added Lines %
asset/asset.go 3 5 60.0%
itest/assertions.go 0 3 0.0%
itest/test_harness.go 1 5 20.0%
rpcserver.go 10 15 66.67%
tapfreighter/chain_porter.go 40 45 88.89%
tapfreighter/coin_select.go 23 29 79.31%
tapfreighter/wallet.go 59 80 73.75%
tapdb/assets_store.go 106 149 71.14%
Files with Coverage Reduction New Missed Lines %
fn/context_guard.go 1 91.94%
fn/func.go 2 58.82%
tapdb/assets_common.go 2 77.97%
tapdb/migrations.go 2 76.19%
tapdb/sqlc/transfers.sql.go 2 82.65%
tapdb/universe_federation.go 2 88.55%
itest/assertions.go 3 87.33%
itest/multisig.go 3 97.94%
proof/courier.go 3 79.57%
tapdb/sqlc/db_custom.go 3 70.83%
Totals Coverage Status
Change from base Build 19360481010: 6.7%
Covered Lines: 64244
Relevant Lines: 114169

💛 - Coveralls

@levmi levmi moved this from 🆕 New to 🏗 In progress in Taproot-Assets Project Board Oct 2, 2025
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from f3a3bff to f55b6c5 Compare October 3, 2025 16:21
@darioAnongba darioAnongba changed the base branch from main to 0-8-0-staging October 6, 2025 09:43
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch 3 times, most recently from 3bd769d to 6fe11a5 Compare October 6, 2025 15:03
@darioAnongba darioAnongba changed the base branch from 0-8-0-staging to main October 6, 2025 15:03
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch 10 times, most recently from a8f3ce4 to afbfebf Compare October 9, 2025 13:04
@darioAnongba darioAnongba marked this pull request as ready for review October 9, 2025 13:09
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch 4 times, most recently from bf3e3ee to d812a8e Compare October 9, 2025 16:04
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from d812a8e to 0ceaf76 Compare October 9, 2025 16:32
@darioAnongba darioAnongba moved this from 🏗 In progress to 👀 In review in Taproot-Assets Project Board Oct 9, 2025
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch 4 times, most recently from ef93717 to d9383ba Compare October 28, 2025 18:58
Copy link
Member

@GeorgeTsagk GeorgeTsagk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last nits, 99% there

@ffranr ffranr added this to the v0.8 milestone Oct 30, 2025
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from d9383ba to 773c448 Compare October 30, 2025 13:26
Copy link
Member

@GeorgeTsagk GeorgeTsagk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from 773c448 to 4fb0135 Compare October 30, 2025 15:58
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch 4 times, most recently from 1cf422a to 66faf3f Compare November 10, 2025 21:00
@darioAnongba darioAnongba requested a review from ffranr November 10, 2025 21:31
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from 66faf3f to 61a19e9 Compare November 14, 2025 09:51
@lightninglabs-deploy
Copy link

@ffranr: review reminder

Copy link
Contributor

@ffranr ffranr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should double check our logic around coin release but otherwise just nits.

Comment on lines +2648 to +2652
LeaseExpiry: sql.NullTime{
Time: finalLeaseExpiry.UTC(),
Valid: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a helper like sqlInt16

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no such thing as a sqlTime. I could add one but then I'll have to change everywhere sql.NullTime is used.

Comment on lines +64 to +86
// Send full amount of the new asset. This should sweep Alice's
// first tombstone and create a new one.
bobAddr2, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{
AssetId: genInfo2.AssetId,
Amt: assetAmount,
AssetVersion: rpcAssets2[0].Version,
})
require.NoError(t.t, err)

sendResp2, _ := sendAssetsToAddr(t, t.tapd, bobAddr2)

ConfirmAndAssertOutboundTransfer(
t.t, t.lndHarness.Miner().Client, t.tapd, sendResp2,
genInfo2.AssetId,
[]uint64{0, assetAmount}, 1, 2,
)
AssertNonInteractiveRecvComplete(t.t, secondTapd, 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can inspect this transaction to ensure that the additional zero-value tombstone input is present.

Comment on lines -1328 to -1337
require.NoError(t, err)

transferResp, err := sender.ListTransfers(
ctxb, &taprpc.ListTransfersRequest{},
)
require.NoError(t, err)

transferRespJSON, err := formatProtoJSON(transferResp)
require.NoError(t, err)
t.Logf("Got response from list transfers: %v", transferRespJSON)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove these lines? That doesn't seem to fix under the commit subject. Same further above also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that I shouldn't remove these logs in this PR or that I should move them to a separate commit?

Why remove these lines?

They're only there to dump the entirety of the responses into the console, which serves no purpose (we should use require to validate assertions).
I've been particularly annoyed by these logs so I try to remove them when I can. Happy to revert or create a dedicated PR.

@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from 61a19e9 to b45eb88 Compare November 21, 2025 15:26
@darioAnongba darioAnongba force-pushed the feat/zero-value-utxo-selection branch from b45eb88 to a686922 Compare November 21, 2025 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

wallet: garbage collect tombstone UTXOs

6 participants