Don't relay resurrected transactions.

This commit modifies the transaction memory pool handling so that it does
not relay resurrected transactions.  The other peers on the network will
also be reorganizing to the same block, so they already know about them.
This commit is contained in:
Dave Collins 2013-11-15 01:50:02 -06:00
parent 9fb17c3a6d
commit 166f8c9ae5
2 changed files with 35 additions and 12 deletions

View file

@ -669,7 +669,7 @@ func (b *blockManager) handleNotifyMsg(notification *btcchain.Notification) {
// Reinsert all of the transactions (except the coinbase) into // Reinsert all of the transactions (except the coinbase) into
// the transaction pool. // the transaction pool.
for _, tx := range block.Transactions()[1:] { for _, tx := range block.Transactions()[1:] {
err := b.server.txMemPool.ProcessTransaction(tx) err := b.server.txMemPool.MaybeAcceptTransaction(tx, nil)
if err != nil { if err != nil {
// 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

View file

@ -663,14 +663,15 @@ func (mp *txMemPool) FetchTransaction(txHash *btcwire.ShaHash) (*btcutil.Tx, err
return nil, fmt.Errorf("transaction is not in the pool") return nil, fmt.Errorf("transaction is not in the pool")
} }
// maybeAcceptTransaction is the main workhorse for handling insertion of new // maybeAcceptTransaction is the internal function which implements the public
// free-standing transactions into a memory pool. It includes functionality // MaybeAcceptTransaction. See the comment for MaybeAcceptTransaction for
// such as rejecting duplicate transactions, ensuring transactions follow all // more details.
// rules, orphan transaction handling, and insertion into the memory pool.
// //
// 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) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) error { func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) error {
if isOrphan != nil {
*isOrphan = false *isOrphan = false
}
txHash := tx.Sha() txHash := tx.Sha()
// Don't accept the transaction if it already exists in the pool. This // Don't accept the transaction if it already exists in the pool. This
@ -765,7 +766,9 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) erro
// Transaction is an orphan if any of the inputs don't exist. // Transaction is an orphan if any of the inputs don't exist.
for _, txD := range txStore { for _, txD := range txStore {
if txD.Err == btcdb.TxShaMissing { if txD.Err == btcdb.TxShaMissing {
if isOrphan != nil {
*isOrphan = true *isOrphan = true
}
return nil return nil
} }
} }
@ -823,13 +826,25 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) erro
// TODO(davec): Notifications // TODO(davec): Notifications
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, txHash)
mp.server.RelayInventory(iv)
return nil return nil
} }
// MaybeAcceptTransaction is the main workhorse for handling insertion of new
// free-standing transactions into a memory pool. It includes functionality
// such as rejecting duplicate transactions, ensuring transactions follow all
// rules, orphan transaction handling, and insertion into the memory pool. The
// isOrphan parameter can be nil if the caller does not need to know whether
// or not the transaction is an orphan.
//
// This function is safe for concurrent access.
func (mp *txMemPool) MaybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool) error {
// Protect concurrent access.
mp.Lock()
defer mp.Unlock()
return mp.maybeAcceptTransaction(tx, isOrphan)
}
// processOrphans determines if there are any orphans which depend on the passed // processOrphans determines if there are any orphans which depend on the passed
// transaction hash (they are no longer orphans if true) and potentially accepts // transaction hash (they are no longer orphans if true) and potentially accepts
// them. It repeats the process for the newly accepted transactions (to detect // them. It repeats the process for the newly accepted transactions (to detect
@ -872,7 +887,11 @@ func (mp *txMemPool) processOrphans(hash *btcwire.ShaHash) error {
return err return err
} }
if isOrphan { if !isOrphan {
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
mp.server.RelayInventory(iv)
} else {
mp.removeOrphan(orphanHash) mp.removeOrphan(orphanHash)
} }
@ -907,6 +926,10 @@ func (mp *txMemPool) ProcessTransaction(tx *btcutil.Tx) error {
} }
if !isOrphan { if !isOrphan {
// Generate the inventory vector and relay it.
iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
mp.server.RelayInventory(iv)
// Accept any orphan transactions that depend on this // Accept any orphan transactions that depend on this
// transaction (they are no longer orphans) and repeat for those // transaction (they are no longer orphans) and repeat for those
// accepted transactions until there are no more. // accepted transactions until there are no more.