@@ -21,7 +21,7 @@ use crate::new_index::{
2121 SpendingInfo , SpendingInput , TxHistoryInfo , Utxo ,
2222} ;
2323use crate :: util:: fees:: { make_fee_histogram, TxFeeInfo } ;
24- use crate :: util:: { extract_tx_prevouts, full_hash, has_prevout , is_spendable, Bytes } ;
24+ use crate :: util:: { extract_tx_prevouts, full_hash, get_prev_outpoints , is_spendable, Bytes } ;
2525
2626#[ cfg( feature = "liquid" ) ]
2727use crate :: elements:: asset;
@@ -288,40 +288,57 @@ impl Mempool {
288288 self . backlog_stats = ( BacklogStats :: new ( & self . feeinfo ) , Instant :: now ( ) ) ;
289289 }
290290
291- pub fn add_by_txid ( & mut self , daemon : & Daemon , txid : & Txid ) {
291+ pub fn add_by_txid ( & mut self , daemon : & Daemon , txid : & Txid ) -> Result < ( ) > {
292292 if self . txstore . get ( txid) . is_none ( ) {
293293 if let Ok ( tx) = daemon. getmempooltx ( & txid) {
294294 self . add ( vec ! [ tx] )
295+ } else {
296+ bail ! ( "add_by_txid cannot find {}" , txid) ;
295297 }
298+ } else {
299+ Ok ( ( ) )
296300 }
297301 }
298302
299- fn add ( & mut self , txs : Vec < Transaction > ) {
303+ fn add ( & mut self , txs : Vec < Transaction > ) -> Result < ( ) > {
300304 self . delta
301305 . with_label_values ( & [ "add" ] )
302306 . observe ( txs. len ( ) as f64 ) ;
303307 let _timer = self . latency . with_label_values ( & [ "add" ] ) . start_timer ( ) ;
304308
305- let mut txids = vec ! [ ] ;
306- // Phase 1: add to txstore
307- for tx in txs {
308- let txid = tx. txid ( ) ;
309- txids. push ( txid) ;
309+ let spent_prevouts = get_prev_outpoints ( & txs) ;
310+ let txs_map = txs
311+ . into_iter ( )
312+ . map ( |tx| ( tx. txid ( ) , tx) )
313+ . collect :: < HashMap < _ , _ > > ( ) ;
314+
315+ // Lookup spent prevouts that were funded within the same `add` batch
316+ let mut txos = HashMap :: new ( ) ;
317+ let remain_prevouts = spent_prevouts
318+ . into_iter ( )
319+ . filter ( |prevout| {
320+ if let Some ( prevtx) = txs_map. get ( & prevout. txid ) {
321+ if let Some ( out) = prevtx. output . get ( prevout. vout as usize ) {
322+ txos. insert ( prevout. clone ( ) , out. clone ( ) ) ;
323+ // remove from the list of remaining `prevouts`
324+ return false ;
325+ }
326+ }
327+ true
328+ } )
329+ . collect ( ) ;
330+
331+ // Lookup remaining spent prevouts in mempool & on-chain
332+ // Fails if any are missing.
333+ txos. extend ( self . lookup_txos ( remain_prevouts) ?) ;
334+
335+ // Add to txstore and indexes
336+ for ( txid, tx) in txs_map {
310337 self . txstore . insert ( txid, tx) ;
311- }
312- // Phase 2: index history and spend edges (can fail if some txos cannot be found)
313- let txos = match self . lookup_txos ( self . get_prevouts ( & txids) ) {
314- Ok ( txos) => txos,
315- Err ( err) => {
316- warn ! ( "lookup txouts failed: {}" , err) ;
317- // TODO: should we remove txids from txstore?
318- return ;
319- }
320- } ;
321- for txid in txids {
322- let tx = self . txstore . get ( & txid) . expect ( "missing mempool tx" ) ;
323- let txid_bytes = full_hash ( & txid[ ..] ) ;
338+ let tx = self . txstore . get ( & txid) . expect ( "was just added" ) ;
339+
324340 let prevouts = extract_tx_prevouts ( & tx, & txos, false ) ;
341+ let txid_bytes = full_hash ( & txid[ ..] ) ;
325342
326343 // Get feeinfo for caching and recent tx overview
327344 let feeinfo = TxFeeInfo :: new ( & tx, & prevouts, self . config . network_type ) ;
@@ -395,6 +412,8 @@ impl Mempool {
395412 & mut self . asset_issuance ,
396413 ) ;
397414 }
415+
416+ Ok ( ( ) )
398417 }
399418
400419 fn lookup_txo ( & self , outpoint : & OutPoint ) -> Option < TxOut > {
@@ -423,24 +442,6 @@ impl Mempool {
423442 Ok ( txos)
424443 }
425444
426- fn get_prevouts ( & self , txids : & [ Txid ] ) -> BTreeSet < OutPoint > {
427- let _timer = self
428- . latency
429- . with_label_values ( & [ "get_prevouts" ] )
430- . start_timer ( ) ;
431-
432- txids
433- . iter ( )
434- . map ( |txid| self . txstore . get ( txid) . expect ( "missing mempool tx" ) )
435- . flat_map ( |tx| {
436- tx. input
437- . iter ( )
438- . filter ( |txin| has_prevout ( txin) )
439- . map ( |txin| txin. previous_output )
440- } )
441- . collect ( )
442- }
443-
444445 fn remove ( & mut self , to_remove : HashSet < & Txid > ) {
445446 self . delta
446447 . with_label_values ( & [ "remove" ] )
@@ -510,7 +511,7 @@ impl Mempool {
510511 {
511512 let mut mempool = mempool. write ( ) . unwrap ( ) ;
512513 // Add new transactions
513- mempool. add ( txs_to_add) ;
514+ mempool. add ( txs_to_add) ? ;
514515
515516 mempool
516517 . count
0 commit comments