mempool: convert orphansByPrev from a list to a map.

This is more efficient and prevents duplicate entries which can
lead to no-longer-orphans being attempted be added to the mempool
multiple times.

Bug found by me, debugged with @davecgh, and patch from @davecgh
This commit is contained in:
David Hill 2015-11-12 17:25:03 -05:00
parent 58e2762158
commit 365b1bd156

View file

@ -58,7 +58,7 @@ type txMemPool struct {
server *server server *server
pool map[wire.ShaHash]*TxDesc pool map[wire.ShaHash]*TxDesc
orphans map[wire.ShaHash]*btcutil.Tx orphans map[wire.ShaHash]*btcutil.Tx
orphansByPrev map[wire.ShaHash]*list.List orphansByPrev map[wire.ShaHash]map[wire.ShaHash]*btcutil.Tx
addrindex map[string]map[wire.ShaHash]struct{} // maps address to txs addrindex map[string]map[wire.ShaHash]struct{} // maps address to txs
outpoints map[wire.OutPoint]*btcutil.Tx outpoints map[wire.OutPoint]*btcutil.Tx
lastUpdated time.Time // last time pool was updated lastUpdated time.Time // last time pool was updated
@ -81,16 +81,11 @@ func (mp *txMemPool) removeOrphan(txHash *wire.ShaHash) {
for _, txIn := range tx.MsgTx().TxIn { for _, txIn := range tx.MsgTx().TxIn {
originTxHash := txIn.PreviousOutPoint.Hash originTxHash := txIn.PreviousOutPoint.Hash
if orphans, exists := mp.orphansByPrev[originTxHash]; exists { if orphans, exists := mp.orphansByPrev[originTxHash]; exists {
for e := orphans.Front(); e != nil; e = e.Next() { delete(orphans, *tx.Sha())
if e.Value.(*btcutil.Tx) == tx {
orphans.Remove(e)
break
}
}
// Remove the map entry altogether if there are no // Remove the map entry altogether if there are no
// longer any orphans which depend on it. // longer any orphans which depend on it.
if orphans.Len() == 0 { if len(orphans) == 0 {
delete(mp.orphansByPrev, originTxHash) delete(mp.orphansByPrev, originTxHash)
} }
} }
@ -158,10 +153,11 @@ func (mp *txMemPool) addOrphan(tx *btcutil.Tx) {
mp.orphans[*tx.Sha()] = tx mp.orphans[*tx.Sha()] = tx
for _, txIn := range tx.MsgTx().TxIn { for _, txIn := range tx.MsgTx().TxIn {
originTxHash := txIn.PreviousOutPoint.Hash originTxHash := txIn.PreviousOutPoint.Hash
if mp.orphansByPrev[originTxHash] == nil { if _, exists := mp.orphansByPrev[originTxHash]; !exists {
mp.orphansByPrev[originTxHash] = list.New() mp.orphansByPrev[originTxHash] =
make(map[wire.ShaHash]*btcutil.Tx)
} }
mp.orphansByPrev[originTxHash].PushBack(tx) mp.orphansByPrev[originTxHash][*tx.Sha()] = tx
} }
txmpLog.Debugf("Stored orphan transaction %v (total: %d)", tx.Sha(), txmpLog.Debugf("Stored orphan transaction %v (total: %d)", tx.Sha(),
@ -886,11 +882,7 @@ func (mp *txMemPool) processOrphans(hash *wire.ShaHash) {
continue continue
} }
var enext *list.Element for _, tx := range orphans {
for e := orphans.Front(); e != nil; e = enext {
enext = e.Next()
tx := e.Value.(*btcutil.Tx)
// Remove the orphan from the orphan pool. Current // Remove the orphan from the orphan pool. Current
// behavior requires that all saved orphans with // behavior requires that all saved orphans with
// a newly accepted parent are removed from the orphan // a newly accepted parent are removed from the orphan
@ -1087,7 +1079,7 @@ func newTxMemPool(server *server) *txMemPool {
server: server, server: server,
pool: make(map[wire.ShaHash]*TxDesc), pool: make(map[wire.ShaHash]*TxDesc),
orphans: make(map[wire.ShaHash]*btcutil.Tx), orphans: make(map[wire.ShaHash]*btcutil.Tx),
orphansByPrev: make(map[wire.ShaHash]*list.List), orphansByPrev: make(map[wire.ShaHash]map[wire.ShaHash]*btcutil.Tx),
outpoints: make(map[wire.OutPoint]*btcutil.Tx), outpoints: make(map[wire.OutPoint]*btcutil.Tx),
} }
if cfg.AddrIndex { if cfg.AddrIndex {