chainntnfs/txnotifier: batch update confirm and spends hints for scripts

This commit is contained in:
Wilmer Paulino 2018-12-06 21:13:53 -08:00
parent f4f5c1ef8b
commit 8042d4f1c8
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F

@ -1474,59 +1474,57 @@ func (n *TxNotifier) DisconnectTip(blockHeight uint32) error {
} }
// updateHints attempts to update the confirm and spend hints for all relevant // updateHints attempts to update the confirm and spend hints for all relevant
// transactions and outpoints respectively. The height parameter is used to // requests respectively. The height parameter is used to determine which
// determine which transactions and outpoints we should update based on whether // requests we should update based on whether a new block is being
// a new block is being connected/disconnected. // connected/disconnected.
// //
// NOTE: This must be called with the TxNotifier's lock held and after its // NOTE: This must be called with the TxNotifier's lock held and after its
// height has already been reflected by a block being connected/disconnected. // height has already been reflected by a block being connected/disconnected.
func (n *TxNotifier) updateHints(height uint32) { func (n *TxNotifier) updateHints(height uint32) {
// TODO(wilmer): update under one database transaction. // TODO(wilmer): update under one database transaction.
// //
// To update the height hint for all the required transactions under one // To update the height hint for all the required confirmation requests
// database transaction, we'll gather the set of unconfirmed // under one database transaction, we'll gather the set of unconfirmed
// transactions along with the ones that confirmed at the height being // requests along with the ones that confirmed at the height being
// connected/disconnected. // connected/disconnected.
txsToUpdateHints := n.unconfirmedTxs() confRequests := n.unconfirmedRequests()
for confirmedTx := range n.txsByInitialHeight[height] { for confRequest := range n.confsByInitialHeight[height] {
txsToUpdateHints = append(txsToUpdateHints, confirmedTx) confRequests = append(confRequests, confRequest)
} }
err := n.confirmHintCache.CommitConfirmHint( err := n.confirmHintCache.CommitConfirmHint(
n.currentHeight, txsToUpdateHints..., n.currentHeight, confRequests...,
) )
if err != nil { if err != nil {
// The error is not fatal as this is an optimistic optimization, // The error is not fatal as this is an optimistic optimization,
// so we'll avoid returning an error. // so we'll avoid returning an error.
Log.Debugf("Unable to update confirm hints to %d for "+ Log.Debugf("Unable to update confirm hints to %d for "+
"%v: %v", n.currentHeight, txsToUpdateHints, err) "%v: %v", n.currentHeight, confRequests, err)
} }
// Similarly, to update the height hint for all the required outpoints // Similarly, to update the height hint for all the required spend
// under one database transaction, we'll gather the set of unspent // requests under one database transaction, we'll gather the set of
// outpoints along with the ones that were spent at the height being // unspent requests along with the ones that were spent at the height
// connected/disconnected. // being connected/disconnected.
opsToUpdateHints := n.unspentOutPoints() spendRequests := n.unspentRequests()
for spentOp := range n.opsBySpendHeight[height] { for spendRequest := range n.spendsByHeight[height] {
opsToUpdateHints = append(opsToUpdateHints, spentOp) spendRequests = append(spendRequests, spendRequest)
} }
err = n.spendHintCache.CommitSpendHint( err = n.spendHintCache.CommitSpendHint(n.currentHeight, spendRequests...)
n.currentHeight, opsToUpdateHints...,
)
if err != nil { if err != nil {
// The error is not fatal as this is an optimistic optimization, // The error is not fatal as this is an optimistic optimization,
// so we'll avoid returning an error. // so we'll avoid returning an error.
Log.Debugf("Unable to update spend hints to %d for "+ Log.Debugf("Unable to update spend hints to %d for "+
"%v: %v", n.currentHeight, opsToUpdateHints, err) "%v: %v", n.currentHeight, spendRequests, err)
} }
} }
// unconfirmedTxs returns the set of transactions that are still seen as // unconfirmedRequests returns the set of confirmation requests that are
// unconfirmed by the TxNotifier. // still seen as unconfirmed by the TxNotifier.
// //
// NOTE: This method must be called with the TxNotifier's lock held. // NOTE: This method must be called with the TxNotifier's lock held.
func (n *TxNotifier) unconfirmedTxs() []chainhash.Hash { func (n *TxNotifier) unconfirmedRequests() []ConfRequest {
var unconfirmedTxs []chainhash.Hash var unconfirmed []ConfRequest
for tx, confNtfnSet := range n.confNotifications { for confRequest, confNtfnSet := range n.confNotifications {
// If the notification is already aware of its confirmation // If the notification is already aware of its confirmation
// details, or it's in the process of learning them, we'll skip // details, or it's in the process of learning them, we'll skip
// it as we can't yet determine if it's confirmed or not. // it as we can't yet determine if it's confirmed or not.
@ -1535,19 +1533,19 @@ func (n *TxNotifier) unconfirmedTxs() []chainhash.Hash {
continue continue
} }
unconfirmedTxs = append(unconfirmedTxs, tx) unconfirmed = append(unconfirmed, confRequest)
} }
return unconfirmedTxs return unconfirmed
} }
// unspentOutPoints returns the set of outpoints that are still seen as unspent // unspentRequests returns the set of spend requests that are still seen as
// by the TxNotifier. // unspent by the TxNotifier.
// //
// NOTE: This method must be called with the TxNotifier's lock held. // NOTE: This method must be called with the TxNotifier's lock held.
func (n *TxNotifier) unspentOutPoints() []wire.OutPoint { func (n *TxNotifier) unspentRequests() []SpendRequest {
var unspentOps []wire.OutPoint var unspent []SpendRequest
for op, spendNtfnSet := range n.spendNotifications { for spendRequest, spendNtfnSet := range n.spendNotifications {
// If the notification is already aware of its spend details, or // If the notification is already aware of its spend details, or
// it's in the process of learning them, we'll skip it as we // it's in the process of learning them, we'll skip it as we
// can't yet determine if it's unspent or not. // can't yet determine if it's unspent or not.
@ -1556,10 +1554,10 @@ func (n *TxNotifier) unspentOutPoints() []wire.OutPoint {
continue continue
} }
unspentOps = append(unspentOps, op) unspent = append(unspent, spendRequest)
} }
return unspentOps return unspent
} }
// dispatchConfReorg dispatches a reorg notification to the client if the // dispatchConfReorg dispatches a reorg notification to the client if the