Skip to content

Commit 5890fcd

Browse files
committed
tapdb: generalise QueryAssetTransfers arg flag unconf_only
This commit renames and generalizes the `unconf_only` argument in the `QueryAssetTransfers` SQL query to `pending_transfers_only`. The flag now returns pending transfers with unconfirmed anchoring transactions or undelivered transfer output proofs. Additionally, this update includes the anchor transaction block hash in the query's returned values. This allows users to determine if a transfer's anchoring transaction has been confirmed on-chain, providing context for why the transfer is pending. As a result of this change, ExportLog.PendingParcels will now also include transfers that are pending due to undelivered proofs, even if their associated anchoring transactions have already been confirmed on-chain.
1 parent 1b5a4ef commit 5890fcd

File tree

6 files changed

+146
-43
lines changed

6 files changed

+146
-43
lines changed

tapdb/assets_store.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,9 +3128,13 @@ func (a *AssetStore) reAnchorPassiveAssets(ctx context.Context,
31283128
return nil
31293129
}
31303130

3131-
// PendingParcels returns the set of parcels that haven't yet been finalized.
3132-
// This can be used to query the set of unconfirmed
3133-
// transactions for re-broadcast.
3131+
// PendingParcels returns the set of parcels that have not yet been finalized.
3132+
// A parcel is considered finalized once the on-chain anchor transaction is
3133+
// included in a block, and all pending transfer output proofs have been
3134+
// delivered to their target peers.
3135+
//
3136+
// NOTE: This can be used to query the set of unconfirmed transactions for
3137+
// re-broadcast and for the set of undelivered proofs.
31343138
func (a *AssetStore) PendingParcels(
31353139
ctx context.Context) ([]*tapfreighter.OutboundParcel, error) {
31363140

@@ -3140,7 +3144,7 @@ func (a *AssetStore) PendingParcels(
31403144
// QueryParcels returns the set of confirmed or unconfirmed parcels.
31413145
func (a *AssetStore) QueryParcels(ctx context.Context,
31423146
anchorTxHash *chainhash.Hash,
3143-
unconfirmedTxOnly bool) ([]*tapfreighter.OutboundParcel, error) {
3147+
pendingTransfersOnly bool) ([]*tapfreighter.OutboundParcel, error) {
31443148

31453149
var (
31463150
outboundParcels []*tapfreighter.OutboundParcel
@@ -3157,10 +3161,8 @@ func (a *AssetStore) QueryParcels(ctx context.Context,
31573161
}
31583162

31593163
transferQuery := TransferQuery{
3160-
// If we want unconfirmed transfers only, we set the
3161-
// UnconfOnly field to true.
3162-
UnconfOnly: unconfirmedTxOnly,
3163-
AnchorTxHash: anchorTxHashBytes,
3164+
AnchorTxHash: anchorTxHashBytes,
3165+
PendingTransfersOnly: sqlBool(pendingTransfersOnly),
31643166
}
31653167

31663168
// Query for asset transfers.
@@ -3210,9 +3212,22 @@ func (a *AssetStore) QueryParcels(ctx context.Context,
32103212
"anchor tx: %w", err)
32113213
}
32123214

3215+
// Marshal anchor tx block hash from the database to a
3216+
// Hash type.
3217+
var anchorTxBlockHash fn.Option[chainhash.Hash]
3218+
if len(dbT.AnchorTxBlockHash) > 0 {
3219+
var blockHash chainhash.Hash
3220+
copy(blockHash[:], dbT.AnchorTxBlockHash)
3221+
3222+
anchorTxBlockHash = fn.Some[chainhash.Hash](
3223+
blockHash,
3224+
)
3225+
}
3226+
32133227
parcel := &tapfreighter.OutboundParcel{
32143228
AnchorTx: anchorTx,
32153229
AnchorTxHeightHint: uint32(dbT.HeightHint),
3230+
AnchorTxBlockHash: anchorTxBlockHash,
32163231
TransferTime: dbT.TransferTimeUnix.UTC(),
32173232
ChainFees: dbAnchorTx.ChainFees,
32183233
Inputs: inputs,

tapdb/assets_store_test.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,10 +1451,16 @@ func TestAssetExportLog(t *testing.T) {
14511451

14521452
// At this point, we should be able to query for the log parcel, by
14531453
// looking for all unconfirmed transfers.
1454-
assetTransfers, err := db.QueryAssetTransfers(ctx, TransferQuery{})
1454+
assetTransfers, err := db.QueryAssetTransfers(ctx, TransferQuery{
1455+
PendingTransfersOnly: sqlBool(true),
1456+
})
14551457
require.NoError(t, err)
14561458
require.Len(t, assetTransfers, 1)
14571459

1460+
// This transfer's anchor transaction is unconfirmed. Therefore, the
1461+
// anchor transaction block hash field of the transfer should be unset.
1462+
require.Empty(t, assetTransfers[0].AnchorTxBlockHash)
1463+
14581464
// We should also be able to find it based on its outpoint.
14591465
firstOutput := spendDelta.Outputs[0]
14601466
firstOutputAnchor := firstOutput.Anchor
@@ -1494,7 +1500,7 @@ func TestAssetExportLog(t *testing.T) {
14941500
// Finally, if we look for the set of confirmed transfers, nothing
14951501
// should be returned.
14961502
assetTransfers, err = db.QueryAssetTransfers(ctx, TransferQuery{
1497-
UnconfOnly: true,
1503+
PendingTransfersOnly: sqlBool(true),
14981504
})
14991505
require.NoError(t, err)
15001506
require.Len(t, assetTransfers, 1)
@@ -2088,7 +2094,33 @@ func TestTransferOutputProofDeliveryStatus(t *testing.T) {
20882094

20892095
// At this point, we should be able to query for the log parcel, by
20902096
// looking for all unconfirmed transfers.
2091-
assetTransfers, err := db.QueryAssetTransfers(ctx, TransferQuery{})
2097+
assetTransfers, err := db.QueryAssetTransfers(ctx, TransferQuery{
2098+
PendingTransfersOnly: sqlBool(true),
2099+
})
2100+
require.NoError(t, err)
2101+
require.Len(t, assetTransfers, 1)
2102+
2103+
// This transfer's anchor transaction is unconfirmed. Therefore, the
2104+
// anchor transaction block hash field of the transfer should be unset.
2105+
require.Empty(t, assetTransfers[0].AnchorTxBlockHash)
2106+
2107+
// At this point we will confirm the anchor tx on-chain.
2108+
assetTransfer := assetTransfers[0]
2109+
randBlockHash := test.RandHash()
2110+
2111+
err = db.ConfirmChainAnchorTx(ctx, AnchorTxConf{
2112+
Txid: assetTransfer.Txid,
2113+
BlockHash: randBlockHash[:],
2114+
BlockHeight: sqlInt32(441),
2115+
TxIndex: sqlInt32(1),
2116+
})
2117+
require.NoError(t, err)
2118+
2119+
// Ensure that parcel is still pending. It should be pending due to the
2120+
// incomplete proof delivery status of some transfer outputs.
2121+
assetTransfers, err = db.QueryAssetTransfers(ctx, TransferQuery{
2122+
PendingTransfersOnly: sqlBool(true),
2123+
})
20922124
require.NoError(t, err)
20932125
require.Len(t, assetTransfers, 1)
20942126

@@ -2140,4 +2172,35 @@ func TestTransferOutputProofDeliveryStatus(t *testing.T) {
21402172
require.Equal(
21412173
t, sql.NullBool{}, transferOutputs[1].ProofDeliveryComplete,
21422174
)
2175+
2176+
// At this point the anchoring transaction has been confirmed on-chain
2177+
// and the proof delivery status shows complete for all applicable
2178+
// transfer outputs. Therefore, we should not be able to find any
2179+
// pending transfers.
2180+
assetTransfers, err = db.QueryAssetTransfers(ctx, TransferQuery{
2181+
PendingTransfersOnly: sqlBool(true),
2182+
})
2183+
require.NoError(t, err)
2184+
require.Len(t, assetTransfers, 0)
2185+
2186+
// Given that the asset transfer is completely finalised, we should be
2187+
// able to find it among the confirmed transfers. We will test this by
2188+
// retrieving the transfer by not specifying the pending transfers only
2189+
// flag and, in another attempt, by setting the flag to false.
2190+
assetTransfers, err = db.QueryAssetTransfers(ctx, TransferQuery{})
2191+
require.NoError(t, err)
2192+
require.Len(t, assetTransfers, 1)
2193+
2194+
assetTransfers, err = db.QueryAssetTransfers(ctx, TransferQuery{
2195+
PendingTransfersOnly: sqlBool(false),
2196+
})
2197+
require.NoError(t, err)
2198+
require.Len(t, assetTransfers, 1)
2199+
2200+
// Ensure that the anchor transaction is confirmed on-chain by verifying
2201+
// that the anchor transaction block hash field on the transfer is
2202+
// correctly set.
2203+
require.Equal(
2204+
t, randBlockHash[:], assetTransfers[0].AnchorTxBlockHash,
2205+
)
21432206
}

tapdb/sqlc/querier.go

Lines changed: 0 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/sqlc/queries/transfers.sql

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,30 @@ WHERE output_id = (SELECT output_id FROM target);
4343

4444
-- name: QueryAssetTransfers :many
4545
SELECT
46-
id, height_hint, txns.txid, transfer_time_unix
46+
id, height_hint, txns.txid, txns.block_hash AS anchor_tx_block_hash,
47+
transfer_time_unix
4748
FROM asset_transfers transfers
4849
JOIN chain_txns txns
49-
ON transfers.anchor_txn_id = txns.txn_id
50-
-- We'll use this clause to filter out for only transfers that are
51-
-- unconfirmed. But only if the unconf_only field is set.
52-
WHERE (@unconf_only = false OR @unconf_only IS NULL OR
53-
(CASE WHEN txns.block_hash IS NULL THEN true ELSE false END) = @unconf_only)
50+
ON txns.txn_id = transfers.anchor_txn_id
51+
WHERE
52+
-- Optionally filter on a given anchor_tx_hash.
53+
(txns.txid = sqlc.narg('anchor_tx_hash')
54+
OR sqlc.narg('anchor_tx_hash') IS NULL)
5455

55-
-- Here we have another optional query clause to select a given transfer
56-
-- based on the anchor_tx_hash, but only if it's specified.
57-
AND (txns.txid = sqlc.narg('anchor_tx_hash') OR
58-
sqlc.narg('anchor_tx_hash') IS NULL)
56+
-- Filter for pending transfers only if requested.
57+
AND (
58+
@pending_transfers_only = true AND
59+
(
60+
txns.block_hash IS NULL
61+
OR EXISTS (
62+
SELECT 1
63+
FROM asset_transfer_outputs outputs
64+
WHERE outputs.transfer_id = transfers.id
65+
AND outputs.proof_delivery_complete = false
66+
)
67+
)
68+
OR @pending_transfers_only = false OR @pending_transfers_only IS NULL
69+
)
5970
ORDER BY transfer_time_unix;
6071

6172
-- name: FetchTransferInputs :many

tapdb/sqlc/transfers.sql.go

Lines changed: 31 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapfreighter/interface.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ type OutboundParcel struct {
314314
// confirmations.
315315
AnchorTxHeightHint uint32
316316

317+
// AnchorTxBlockHash is the block hash of the block that contains the
318+
// anchor transaction. This is set once the anchor transaction is
319+
// confirmed.
320+
AnchorTxBlockHash fn.Option[chainhash.Hash]
321+
317322
// TransferTime holds the timestamp of the outbound spend.
318323
TransferTime time.Time
319324

0 commit comments

Comments
 (0)