@@ -206,9 +206,7 @@ impl Mempool {
206
206
TxHistoryInfo :: Funding ( info) => {
207
207
// Liquid requires some additional information from the txo that's not available in the TxHistoryInfo index.
208
208
#[ cfg( feature = "liquid" ) ]
209
- let txo = self
210
- . lookup_txo ( & entry. get_funded_outpoint ( ) )
211
- . expect ( "missing txo" ) ;
209
+ let txo = self . lookup_txo ( & entry. get_funded_outpoint ( ) ) ?;
212
210
213
211
Some ( Utxo {
214
212
txid : deserialize ( & info. txid ) . expect ( "invalid txid" ) ,
@@ -345,7 +343,9 @@ impl Mempool {
345
343
}
346
344
} ;
347
345
// Add new transactions
348
- self . add ( to_add) ?;
346
+ if to_add. len ( ) > self . add ( to_add) {
347
+ debug ! ( "Mempool update added less transactions than expected" ) ;
348
+ }
349
349
// Remove missing transactions
350
350
self . remove ( to_remove) ;
351
351
@@ -370,39 +370,66 @@ impl Mempool {
370
370
pub fn add_by_txid ( & mut self , daemon : & Daemon , txid : & Txid ) -> Result < ( ) > {
371
371
if self . txstore . get ( txid) . is_none ( ) {
372
372
if let Ok ( tx) = daemon. getmempooltx ( txid) {
373
- self . add ( vec ! [ tx] ) ?;
373
+ if self . add ( vec ! [ tx] ) == 0 {
374
+ return Err ( format ! (
375
+ "Unable to add {txid} to mempool likely due to missing parents."
376
+ )
377
+ . into ( ) ) ;
378
+ }
374
379
}
375
380
}
376
-
377
381
Ok ( ( ) )
378
382
}
379
383
380
- fn add ( & mut self , txs : Vec < Transaction > ) -> Result < ( ) > {
384
+ /// Add transactions to the mempool.
385
+ ///
386
+ /// The return value is the number of transactions processed.
387
+ #[ must_use = "Must deal with [[input vec's length]] > [[result]]." ]
388
+ fn add ( & mut self , txs : Vec < Transaction > ) -> usize {
381
389
self . delta
382
390
. with_label_values ( & [ "add" ] )
383
391
. observe ( txs. len ( ) as f64 ) ;
384
392
let _timer = self . latency . with_label_values ( & [ "add" ] ) . start_timer ( ) ;
393
+ let txlen = txs. len ( ) ;
394
+ if txlen == 0 {
395
+ return 0 ;
396
+ }
397
+ debug ! ( "Adding {} transactions to Mempool" , txlen) ;
385
398
386
- let mut txids = vec ! [ ] ;
399
+ let mut txids = Vec :: with_capacity ( txs . len ( ) ) ;
387
400
// Phase 1: add to txstore
388
401
for tx in txs {
389
402
let txid = tx. txid ( ) ;
390
403
txids. push ( txid) ;
391
404
self . txstore . insert ( txid, tx) ;
392
405
}
393
- // Phase 2: index history and spend edges (can fail if some txos cannot be found)
394
- let txos = match self . lookup_txos ( & self . get_prevouts ( & txids) ) {
395
- Ok ( txos) => txos,
396
- Err ( err) => {
397
- warn ! ( "lookup txouts failed: {}" , err) ;
398
- // TODO: should we remove txids from txstore?
399
- return Ok ( ( ) ) ;
400
- }
401
- } ;
406
+
407
+ // Phase 2: index history and spend edges (some txos can be missing)
408
+ let txos = self . lookup_txos ( & self . get_prevouts ( & txids) ) ;
409
+
410
+ // Count how many transactions were actually processed.
411
+ let mut processed_count = 0 ;
412
+
413
+ // Phase 3: Iterate over the transactions and do the following:
414
+ // 1. Find all of the TxOuts of each input parent using `txos`
415
+ // 2. If any parent wasn't found, skip parsing this transaction
416
+ // 3. Insert TxFeeInfo into info.
417
+ // 4. Push TxOverview into recent tx queue.
418
+ // 5. Create the Spend and Fund TxHistory structs for inputs + outputs
419
+ // 6. Insert all TxHistory into history.
420
+ // 7. Insert the tx edges into edges (HashMap of (Outpoint, (Txid, vin)))
421
+ // 8. (Liquid only) Parse assets of tx.
402
422
for txid in txids {
403
- let tx = self . txstore . get ( & txid) . expect ( "missing mempool tx" ) ;
423
+ let tx = self . txstore . get ( & txid) . expect ( "missing tx from txstore" ) ;
424
+
425
+ let prevouts = match extract_tx_prevouts ( tx, & txos, false ) {
426
+ Ok ( v) => v,
427
+ Err ( e) => {
428
+ warn ! ( "Skipping tx {txid} missing parent error: {e}" ) ;
429
+ continue ;
430
+ }
431
+ } ;
404
432
let txid_bytes = full_hash ( & txid[ ..] ) ;
405
- let prevouts = extract_tx_prevouts ( tx, & txos, false ) ?;
406
433
407
434
// Get feeinfo for caching and recent tx overview
408
435
let feeinfo = TxFeeInfo :: new ( tx, & prevouts, self . config . network_type ) ;
@@ -472,18 +499,26 @@ impl Mempool {
472
499
& mut self . asset_history ,
473
500
& mut self . asset_issuance ,
474
501
) ;
502
+
503
+ processed_count += 1 ;
475
504
}
476
505
477
- Ok ( ( ) )
506
+ processed_count
478
507
}
479
508
480
- pub fn lookup_txo ( & self , outpoint : & OutPoint ) -> Result < TxOut > {
509
+ /// Returns None if the lookup fails (mempool transaction RBF-ed etc.)
510
+ pub fn lookup_txo ( & self , outpoint : & OutPoint ) -> Option < TxOut > {
481
511
let mut outpoints = BTreeSet :: new ( ) ;
482
512
outpoints. insert ( * outpoint) ;
483
- Ok ( self . lookup_txos ( & outpoints) ?. remove ( outpoint) . unwrap ( ) )
513
+ // This can possibly be None now
514
+ self . lookup_txos ( & outpoints) . remove ( outpoint)
484
515
}
485
516
486
- pub fn lookup_txos ( & self , outpoints : & BTreeSet < OutPoint > ) -> Result < HashMap < OutPoint , TxOut > > {
517
+ /// For a given set of OutPoints, return a HashMap<OutPoint, TxOut>
518
+ ///
519
+ /// Not all OutPoints from mempool transactions are guaranteed to be there.
520
+ /// Ensure you deal with the None case in your logic.
521
+ pub fn lookup_txos ( & self , outpoints : & BTreeSet < OutPoint > ) -> HashMap < OutPoint , TxOut > {
487
522
let _timer = self
488
523
. latency
489
524
. with_label_values ( & [ "lookup_txos" ] )
@@ -494,18 +529,21 @@ impl Mempool {
494
529
let mempool_txos = outpoints
495
530
. iter ( )
496
531
. filter ( |outpoint| !confirmed_txos. contains_key ( outpoint) )
497
- . map ( |outpoint| {
532
+ . flat_map ( |outpoint| {
498
533
self . txstore
499
534
. get ( & outpoint. txid )
500
535
. and_then ( |tx| tx. output . get ( outpoint. vout as usize ) . cloned ( ) )
501
536
. map ( |txout| ( * outpoint, txout) )
502
- . chain_err ( || format ! ( "missing outpoint {:?}" , outpoint) )
537
+ . or_else ( || {
538
+ warn ! ( "missing outpoint {:?}" , outpoint) ;
539
+ None
540
+ } )
503
541
} )
504
- . collect :: < Result < HashMap < OutPoint , TxOut > > > ( ) ? ;
542
+ . collect :: < HashMap < OutPoint , TxOut > > ( ) ;
505
543
506
544
let mut txos = confirmed_txos;
507
545
txos. extend ( mempool_txos) ;
508
- Ok ( txos)
546
+ txos
509
547
}
510
548
511
549
fn get_prevouts ( & self , txids : & [ Txid ] ) -> BTreeSet < OutPoint > {
0 commit comments