chainntnfs: signal reorg notification before required confirmations

In this commit, we send the reorg notification even when the
transaction has not yet reached the required confirmations, in
case the caller is interested in knowing about it.

Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
This commit is contained in:
Nishant Bansal committed 2025-09-11 18:24:54 +05:30
1 parent 0c2f045f5d
commit aa9c3272e3
2 files changed
+64

No files matched your search

+14
View File
@@ -2011,6 +2011,20 @@ func (n *TxNotifier) dispatchConfReorg(ntfn *ConfNtfn,
if !ntfn.dispatched {
confHeight := heightDisconnected + ntfn.NumConfirmations - 1
ntfnSet, exists := n.ntfnsByConfirmHeight[confHeight]
// We also signal the reorg to the notifier in case the
// subscriber is also interested in the reorgs before the
// transaction received its required confirmation.
//
// Because as soon as a new block is connected which has the
// transaction included again we preemptively read the buffered
// channel.
select {
case ntfn.Event.NegativeConf <- int32(n.reorgDepth):
case <-n.quit:
return ErrTxNotifierExiting
}
if exists {
delete(ntfnSet, ntfn)
}
+50
View File
@@ -1548,6 +1548,56 @@ func TestTxNotifierConfReorg(t *testing.T) {
}
}
// TestTxNotifierReorgPartialConfirmation ensures that a tx with intermediate
// confirmations handles a reorg correctly and emits the appropriate reorg ntfn.
func TestTxNotifierReorgPartialConfirmation(t *testing.T) {
t.Parallel()
const txNumConfs uint32 = 2
hintCache := newMockHintCache()
n := chainntnfs.NewTxNotifier(
7, chainntnfs.ReorgSafetyLimit, hintCache, hintCache,
)
// Tx will be confirmed in block 9 and requires 2 confs.
tx := wire.MsgTx{Version: 1}
tx.AddTxOut(&wire.TxOut{PkScript: testRawScript})
txHash := tx.TxHash()
ntfn, err := n.RegisterConf(&txHash, testRawScript, txNumConfs, 1)
require.NoError(t, err, "unable to register ntfn")
err = n.UpdateConfDetails(ntfn.HistoricalDispatch.ConfRequest, nil)
require.NoError(t, err, "unable to deliver conf details")
// Mine 1 block to satisfy the requirement for a partially confirmed tx.
block := btcutil.NewBlock(&wire.MsgBlock{
Transactions: []*wire.MsgTx{&tx},
})
err = n.ConnectTip(block, 8)
require.NoError(t, err, "failed to connect block")
err = n.NotifyHeight(8)
require.NoError(t, err, "unable to dispatch notifications")
// Now that the transaction is partially confirmed, reorg out those
// blocks.
err = n.DisconnectTip(8)
require.NoError(t, err, "unable to disconnect block")
// After the intermediate confirmation is reorged out, the tx should not
// trigger a confirmation ntfn, but should trigger a reorg ntfn.
select {
case <-ntfn.Event.Confirmed:
t.Fatal("unexpected confirmation after reorg")
default:
}
select {
case <-ntfn.Event.NegativeConf:
default:
t.Fatal("expected to receive reorg notification")
}
}
// TestTxNotifierSpendReorg ensures that clients are notified of a reorg when
// the spending transaction of an outpoint for which they registered a spend
// notification for has been reorged out of the chain.