chainntnfs/bitcoindnotify: filter out mempool spends from relevant txs

This commit fix a bug within the bitcoind notifier logic, which would
ignore the passed mempool argument, and notify spentness whether the
spending transaction was confirmed or not. The logic used to fix this is
similar to what is already done for the btcd backend.
This commit is contained in:
Johan T. Halseth
2018-07-13 12:35:29 +02:00
parent b0288d4677
commit 4e47e4e7f1

View File

@@ -352,16 +352,40 @@ func (b *BitcoindNotifier) handleRelevantTx(tx chain.RelevantTx, bestHeight int3
// TODO(roasbeef): after change to // TODO(roasbeef): after change to
// loadfilter, only notify on block // loadfilter, only notify on block
// inclusion? // inclusion?
confirmedSpend := false
if tx.Block != nil { if tx.Block != nil {
confirmedSpend = true
spendDetails.SpendingHeight = tx.Block.Height spendDetails.SpendingHeight = tx.Block.Height
} else { } else {
spendDetails.SpendingHeight = bestHeight + 1 spendDetails.SpendingHeight = bestHeight + 1
} }
for _, ntfn := range clients { // Keep spendNotifications that are
chainntnfs.Log.Infof("Dispatching "+ // waiting for a confirmation around.
// They will be notified when we find
// the spend within a block.
rem := make(map[uint64]*spendNotification)
for c, ntfn := range clients {
// If this is a mempool spend,
// and this client didn't want
// to be notified on mempool
// spends, store it for later.
if !confirmedSpend && !ntfn.mempool {
rem[c] = ntfn
continue
}
confStr := "unconfirmed"
if confirmedSpend {
confStr = "confirmed"
}
chainntnfs.Log.Infof("Dispatching %s "+
"spend notification for "+ "spend notification for "+
"outpoint=%v", ntfn.targetOutpoint) "outpoint=%v at height %v",
confStr, ntfn.targetOutpoint,
spendDetails.SpendingHeight)
ntfn.spendChan <- spendDetails ntfn.spendChan <- spendDetails
// Close spendChan to ensure that any calls to Cancel will not // Close spendChan to ensure that any calls to Cancel will not
@@ -370,6 +394,12 @@ func (b *BitcoindNotifier) handleRelevantTx(tx chain.RelevantTx, bestHeight int3
close(ntfn.spendChan) close(ntfn.spendChan)
} }
delete(b.spendNotifications, prevOut) delete(b.spendNotifications, prevOut)
// If we had any clients left, add them
// back to the map.
if len(rem) > 0 {
b.spendNotifications[prevOut] = rem
}
} }
} }
} }
@@ -530,6 +560,8 @@ type spendNotification struct {
spendID uint64 spendID uint64
heightHint uint32 heightHint uint32
mempool bool
} }
// spendCancel is a message sent to the BitcoindNotifier when a client wishes // spendCancel is a message sent to the BitcoindNotifier when a client wishes
@@ -548,12 +580,13 @@ type spendCancel struct {
// across the 'Spend' channel. The heightHint should represent the earliest // across the 'Spend' channel. The heightHint should represent the earliest
// height in the chain where the transaction could have been spent in. // height in the chain where the transaction could have been spent in.
func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
heightHint uint32, _ bool) (*chainntnfs.SpendEvent, error) { heightHint uint32, mempool bool) (*chainntnfs.SpendEvent, error) {
ntfn := &spendNotification{ ntfn := &spendNotification{
targetOutpoint: outpoint, targetOutpoint: outpoint,
spendChan: make(chan *chainntnfs.SpendDetail, 1), spendChan: make(chan *chainntnfs.SpendDetail, 1),
spendID: atomic.AddUint64(&b.spendClientCounter, 1), spendID: atomic.AddUint64(&b.spendClientCounter, 1),
mempool: mempool,
} }
select { select {