Skip to content

Commit 3108912

Browse files
committed
wallet: test confirmed relevant tx omits sync tip
Add coverage proving a confirmed chain.RelevantTx notification builds an ApplyTxBatch whose transaction carries the confirming block while SyncedTo stays nil, so the standalone notification records the confirmed tx without advancing the wallet sync tip.
1 parent 710fd53 commit 3108912

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

wallet/syncer_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,96 @@ func TestProcessRelevantTxUsesStore(t *testing.T) {
957957
store.AssertExpectations(t)
958958
}
959959

960+
// matchConfirmedTxBatchNoSyncTip returns a matcher asserting a confirmed
961+
// relevant transaction is written as one store batch whose transaction carries
962+
// the confirming block, while SyncedTo stays nil so the standalone
963+
// notification does not advance the wallet sync tip.
964+
func matchConfirmedTxBatchNoSyncTip(walletID uint32, tx *wire.MsgTx,
965+
addr btcutil.Address, received time.Time, block *wtxmgr.BlockMeta) any {
966+
967+
return mock.MatchedBy(func(params db.TxBatchParams) bool {
968+
if params.WalletID != walletID ||
969+
len(params.Transactions) != 1 ||
970+
params.SyncedTo != nil {
971+
972+
return false
973+
}
974+
975+
txParams := params.Transactions[0]
976+
if txParams.Block == nil ||
977+
!matchStoreBlockFields(txParams.Block, block) {
978+
979+
return false
980+
}
981+
982+
return matchRelevantTxParams(
983+
txParams, walletID, tx, addr, received,
984+
)
985+
})
986+
}
987+
988+
// TestProcessRelevantTxUsesStoreConfirmedBlock verifies that a confirmed
989+
// relevant transaction notification (one carrying a block) builds an
990+
// ApplyTxBatch with the transaction's confirming block set but SyncedTo left
991+
// nil, so the standalone notification records the confirmed tx without
992+
// advancing the wallet sync tip. The Store block row is then ensured by the
993+
// SQL applyBatchTransaction path (covered separately on the Store-layer fix).
994+
func TestProcessRelevantTxUsesStoreConfirmedBlock(t *testing.T) {
995+
t.Parallel()
996+
997+
// Arrange: A store-backed syncer and a transaction paying a
998+
// wallet-owned address, confirmed in a block.
999+
const walletID uint32 = 8
1000+
1001+
store := &walletmock.Store{}
1002+
publisher := &mockTxPublisher{}
1003+
s := newSyncer(
1004+
Config{ChainParams: &chainParams}, nil, nil, publisher,
1005+
syncerStoreConfig{store: store, walletID: walletID},
1006+
)
1007+
1008+
addr, err := btcutil.NewAddressPubKeyHash(
1009+
make([]byte, 20), &chainParams,
1010+
)
1011+
require.NoError(t, err)
1012+
1013+
pkScript, err := txscript.PayToAddrScript(addr)
1014+
require.NoError(t, err)
1015+
1016+
tx := wire.NewMsgTx(1)
1017+
tx.AddTxOut(&wire.TxOut{Value: 1000, PkScript: pkScript})
1018+
1019+
received := time.Unix(456, 0).UTC()
1020+
rec, err := wtxmgr.NewTxRecordFromMsgTx(tx, received)
1021+
require.NoError(t, err)
1022+
1023+
block := &wtxmgr.BlockMeta{
1024+
Block: wtxmgr.Block{
1025+
Hash: chainhash.Hash{0x0c},
1026+
Height: 222,
1027+
},
1028+
Time: time.Unix(789, 0).UTC(),
1029+
}
1030+
1031+
expectAddressOwned(t, store, walletID, addr)
1032+
store.On("ApplyTxBatch", mock.Anything,
1033+
matchConfirmedTxBatchNoSyncTip(
1034+
walletID, tx, addr, received, block,
1035+
),
1036+
).Return(nil).Once()
1037+
1038+
// Act: Process a confirmed relevant transaction notification.
1039+
err = s.processChainUpdate(
1040+
t.Context(), chain.RelevantTx{TxRecord: rec, Block: block},
1041+
)
1042+
1043+
// Assert: The batch carries the confirming block but leaves the sync
1044+
// tip untouched. The mock registers only ApplyTxBatch (and address
1045+
// lookups), so any sync-tip write would fail AssertExpectations.
1046+
require.NoError(t, err)
1047+
store.AssertExpectations(t)
1048+
}
1049+
9601050
// matchStoreBlockFields reports whether a store block matches the wtxmgr block
9611051
// metadata's hash, height, and timestamp.
9621052
func matchStoreBlockFields(b *db.Block, block *wtxmgr.BlockMeta) bool {

0 commit comments

Comments
 (0)