Fix mempool transactions disappearing if a parent tx is confirmed.

This commit is contained in:
Dario Nieuwenhuis 2015-11-05 17:27:42 +01:00
parent 4b7206b54f
commit 912a8d8301
2 changed files with 20 additions and 16 deletions

View file

@ -1215,11 +1215,11 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// connected block from the transaction pool. Secondly, remove any // connected block from the transaction pool. Secondly, remove any
// transactions which are now double spends as a result of these // transactions which are now double spends as a result of these
// new transactions. Finally, remove any transaction that is // new transactions. Finally, remove any transaction that is
// no longer an orphan. Note that removing a transaction from // no longer an orphan. Transactions which depend on a confirmed
// pool also removes any transactions which depend on it, // transaction are NOT removed recursively because they are still
// recursively. // valid.
for _, tx := range block.Transactions()[1:] { for _, tx := range block.Transactions()[1:] {
b.server.txMemPool.RemoveTransaction(tx) b.server.txMemPool.RemoveTransaction(tx, false)
b.server.txMemPool.RemoveDoubleSpends(tx) b.server.txMemPool.RemoveDoubleSpends(tx)
b.server.txMemPool.RemoveOrphan(tx.Sha()) b.server.txMemPool.RemoveOrphan(tx.Sha())
b.server.txMemPool.ProcessOrphans(tx.Sha()) b.server.txMemPool.ProcessOrphans(tx.Sha())
@ -1261,7 +1261,7 @@ func (b *blockManager) handleNotifyMsg(notification *blockchain.Notification) {
// Remove the transaction and all transactions // Remove the transaction and all transactions
// that depend on it if it wasn't accepted into // that depend on it if it wasn't accepted into
// the transaction pool. // the transaction pool.
b.server.txMemPool.RemoveTransaction(tx) b.server.txMemPool.RemoveTransaction(tx, true)
} }
} }

View file

@ -398,13 +398,15 @@ func (mp *txMemPool) HaveTransaction(hash *wire.ShaHash) bool {
// RemoveTransaction. See the comment for RemoveTransaction for more details. // RemoveTransaction. See the comment for RemoveTransaction for more details.
// //
// This function MUST be called with the mempool lock held (for writes). // This function MUST be called with the mempool lock held (for writes).
func (mp *txMemPool) removeTransaction(tx *btcutil.Tx) { func (mp *txMemPool) removeTransaction(tx *btcutil.Tx, removeRedeemers bool) {
// Remove any transactions which rely on this one.
txHash := tx.Sha() txHash := tx.Sha()
for i := uint32(0); i < uint32(len(tx.MsgTx().TxOut)); i++ { if removeRedeemers {
outpoint := wire.NewOutPoint(txHash, i) // Remove any transactions which rely on this one.
if txRedeemer, exists := mp.outpoints[*outpoint]; exists { for i := uint32(0); i < uint32(len(tx.MsgTx().TxOut)); i++ {
mp.removeTransaction(txRedeemer) outpoint := wire.NewOutPoint(txHash, i)
if txRedeemer, exists := mp.outpoints[*outpoint]; exists {
mp.removeTransaction(txRedeemer, true)
}
} }
} }
@ -466,16 +468,18 @@ func (mp *txMemPool) removeScriptFromAddrIndex(pkScript []byte, tx *btcutil.Tx)
return nil return nil
} }
// RemoveTransaction removes the passed transaction and any transactions which // RemoveTransaction removes the passed transaction from the mempool. If
// depend on it from the memory pool. // removeRedeemers flag is set, any transactions that redeem outputs from the
// removed transaction will also be removed recursively from the mempool, as
// they would otherwise become orphan.
// //
// This function is safe for concurrent access. // This function is safe for concurrent access.
func (mp *txMemPool) RemoveTransaction(tx *btcutil.Tx) { func (mp *txMemPool) RemoveTransaction(tx *btcutil.Tx, removeRedeemers bool) {
// Protect concurrent access. // Protect concurrent access.
mp.Lock() mp.Lock()
defer mp.Unlock() defer mp.Unlock()
mp.removeTransaction(tx) mp.removeTransaction(tx, removeRedeemers)
} }
// RemoveDoubleSpends removes all transactions which spend outputs spent by the // RemoveDoubleSpends removes all transactions which spend outputs spent by the
@ -493,7 +497,7 @@ func (mp *txMemPool) RemoveDoubleSpends(tx *btcutil.Tx) {
for _, txIn := range tx.MsgTx().TxIn { for _, txIn := range tx.MsgTx().TxIn {
if txRedeemer, ok := mp.outpoints[txIn.PreviousOutPoint]; ok { if txRedeemer, ok := mp.outpoints[txIn.PreviousOutPoint]; ok {
if !txRedeemer.Sha().IsEqual(tx.Sha()) { if !txRedeemer.Sha().IsEqual(tx.Sha()) {
mp.removeTransaction(txRedeemer) mp.removeTransaction(txRedeemer, true)
} }
} }
} }