Skip to content

Commit

Permalink
mempool: handle orphan utreexo txs
Browse files Browse the repository at this point in the history
Utreexo txs get put into the orphan pool but since the udata is no
longer included in the tx, we need to keep track of it separately. This
commit addresses that.
  • Loading branch information
kcalvinalvin committed Nov 17, 2024
1 parent f1bbb10 commit e79bfaa
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
43 changes: 38 additions & 5 deletions mempool/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ type TxPool struct {
pool map[chainhash.Hash]*TxDesc
poolLeaves map[chainhash.Hash][]wire.LeafData
orphans map[chainhash.Hash]*orphanTx
orphanUData map[chainhash.Hash]*wire.UData
orphansByPrev map[wire.OutPoint]map[chainhash.Hash]*btcutil.Tx
outpoints map[wire.OutPoint]*btcutil.Tx
pennyTotal float64 // exponentially decaying total for penny spends.
Expand Down Expand Up @@ -225,6 +226,21 @@ func (mp *TxPool) removeOrphan(tx *btcutil.Tx, removeRedeemers bool) {
return
}

if mp.cfg.IsUtreexoViewActive() {
ud, found := mp.orphanUData[*tx.Hash()]
if found {
// Remove related utreexo data.
//
// TODO uncache from the accumulator.
delete(mp.orphanUData, *tx.Hash())
err := mp.cfg.PruneFromAccumulator(ud.LeafDatas)
if err != nil {
log.Debugf("error while pruning proof for orphan tx %v"+
"from the accumulator.", tx.Hash())
}
}
}

// Remove the reference from the previous orphan index.
for _, txIn := range otx.tx.MsgTx().TxIn {
orphans, exists := mp.orphansByPrev[txIn.PreviousOutPoint]
Expand Down Expand Up @@ -337,7 +353,7 @@ func (mp *TxPool) limitNumOrphans() error {
// addOrphan adds an orphan transaction to the orphan pool.
//
// This function MUST be called with the mempool lock held (for writes).
func (mp *TxPool) addOrphan(tx *btcutil.Tx, tag Tag) {
func (mp *TxPool) addOrphan(tx *btcutil.Tx, utreexoData *wire.UData, tag Tag) {
// Nothing to do if no orphans are allowed.
if mp.cfg.Policy.MaxOrphanTxs <= 0 {
return
Expand All @@ -360,6 +376,12 @@ func (mp *TxPool) addOrphan(tx *btcutil.Tx, tag Tag) {
}
mp.orphansByPrev[txIn.PreviousOutPoint][*tx.Hash()] = tx
}
if mp.cfg.IsUtreexoViewActive() {
// Ingest the proof. Shouldn't error out with the proof being invalid
// here since we've already verified it above.
mp.cfg.VerifyUData(utreexoData, tx.MsgTx().TxIn, true)
mp.orphanUData[*tx.Hash()] = utreexoData
}

log.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(),
len(mp.orphans))
Expand All @@ -368,7 +390,7 @@ func (mp *TxPool) addOrphan(tx *btcutil.Tx, tag Tag) {
// maybeAddOrphan potentially adds an orphan to the orphan pool.
//
// This function MUST be called with the mempool lock held (for writes).
func (mp *TxPool) maybeAddOrphan(tx *btcutil.Tx, tag Tag) error {
func (mp *TxPool) maybeAddOrphan(tx *btcutil.Tx, utreexoData *wire.UData, tag Tag) error {
// Ignore orphan transactions that are too large. This helps avoid
// a memory exhaustion attack based on sending a lot of really large
// orphans. In the case there is a valid transaction larger than this,
Expand All @@ -388,7 +410,7 @@ func (mp *TxPool) maybeAddOrphan(tx *btcutil.Tx, tag Tag) error {
}

// Add the orphan if the none of the above disqualified it.
mp.addOrphan(tx, tag)
mp.addOrphan(tx, utreexoData, tag)

return nil
}
Expand Down Expand Up @@ -1127,8 +1149,18 @@ func (mp *TxPool) processOrphans(acceptedTx *btcutil.Tx) []*TxDesc {

// Potentially accept an orphan into the tx pool.
for _, tx := range orphans {
var uData *wire.UData
if mp.cfg.IsUtreexoViewActive() {
var found bool
uData, found = mp.orphanUData[*tx.Hash()]
if !found {
log.Debugf("is a utreexo node but is missing udata for"+
"orphan tx %v", tx.Hash())
continue
}
}
missing, txD, err := mp.maybeAcceptTransaction(
tx, nil, true, true, false)
tx, uData, true, true, false)
if err != nil {
// The orphan is now invalid, so there
// is no way any other orphans which
Expand Down Expand Up @@ -1252,7 +1284,7 @@ func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, utreexoData *wire.UData, al
}

// Potentially add the orphan transaction to the orphan pool.
err = mp.maybeAddOrphan(tx, tag)
err = mp.maybeAddOrphan(tx, utreexoData, tag)
return nil, err
}

Expand Down Expand Up @@ -1882,6 +1914,7 @@ func New(cfg *Config) *TxPool {
pool: make(map[chainhash.Hash]*TxDesc),
poolLeaves: make(map[chainhash.Hash][]wire.LeafData),
orphans: make(map[chainhash.Hash]*orphanTx),
orphanUData: make(map[chainhash.Hash]*wire.UData),
orphansByPrev: make(map[wire.OutPoint]map[chainhash.Hash]*btcutil.Tx),
nextExpireScan: time.Now().Add(orphanExpireScanInterval),
outpoints: make(map[wire.OutPoint]*btcutil.Tx),
Expand Down
15 changes: 8 additions & 7 deletions mempool/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,14 @@ func newPoolHarness(chainParams *chaincfg.Params) (*poolHarness, []spendableOutp
MinRelayTxFee: 1000, // 1 Satoshi per byte
MaxTxVersion: 1,
},
ChainParams: chainParams,
FetchUtxoView: chain.FetchUtxoView,
BestHeight: chain.BestHeight,
MedianTimePast: chain.MedianTimePast,
CalcSequenceLock: chain.CalcSequenceLock,
SigCache: nil,
AddrIndex: nil,
ChainParams: chainParams,
FetchUtxoView: chain.FetchUtxoView,
IsUtreexoViewActive: func() bool { return false },
BestHeight: chain.BestHeight,
MedianTimePast: chain.MedianTimePast,
CalcSequenceLock: chain.CalcSequenceLock,
SigCache: nil,
AddrIndex: nil,
}),
}

Expand Down

0 comments on commit e79bfaa

Please sign in to comment.