github.com/rumhocker/blockbook@v0.3.2/bchain/basemempool.go (about)

     1  package bchain
     2  
     3  import (
     4  	"sort"
     5  	"sync"
     6  )
     7  
     8  type addrIndex struct {
     9  	addrDesc string
    10  	n        int32
    11  }
    12  
    13  type txEntry struct {
    14  	addrIndexes []addrIndex
    15  	time        uint32
    16  }
    17  
    18  type txidio struct {
    19  	txid string
    20  	io   []addrIndex
    21  }
    22  
    23  // BaseMempool is mempool base handle
    24  type BaseMempool struct {
    25  	chain        BlockChain
    26  	mux          sync.Mutex
    27  	txEntries    map[string]txEntry
    28  	addrDescToTx map[string][]Outpoint
    29  	OnNewTxAddr  OnNewTxAddrFunc
    30  }
    31  
    32  // GetTransactions returns slice of mempool transactions for given address
    33  func (m *BaseMempool) GetTransactions(address string) ([]Outpoint, error) {
    34  	parser := m.chain.GetChainParser()
    35  	addrDesc, err := parser.GetAddrDescFromAddress(address)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	return m.GetAddrDescTransactions(addrDesc)
    40  }
    41  
    42  // GetAddrDescTransactions returns slice of mempool transactions for given address descriptor, in reverse order
    43  func (m *BaseMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]Outpoint, error) {
    44  	m.mux.Lock()
    45  	defer m.mux.Unlock()
    46  	outpoints := m.addrDescToTx[string(addrDesc)]
    47  	rv := make([]Outpoint, len(outpoints))
    48  	for i, j := len(outpoints)-1, 0; i >= 0; i-- {
    49  		rv[j] = outpoints[i]
    50  		j++
    51  	}
    52  	return rv, nil
    53  }
    54  
    55  func (a MempoolTxidEntries) Len() int      { return len(a) }
    56  func (a MempoolTxidEntries) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
    57  func (a MempoolTxidEntries) Less(i, j int) bool {
    58  	// if the Time is equal, sort by txid to make the order defined
    59  	hi := a[i].Time
    60  	hj := a[j].Time
    61  	if hi == hj {
    62  		return a[i].Txid > a[j].Txid
    63  	}
    64  	// order in reverse
    65  	return hi > hj
    66  }
    67  
    68  // removeEntryFromMempool removes entry from mempool structs. The caller is responsible for locking!
    69  func (m *BaseMempool) removeEntryFromMempool(txid string, entry txEntry) {
    70  	delete(m.txEntries, txid)
    71  	for _, si := range entry.addrIndexes {
    72  		outpoints, found := m.addrDescToTx[si.addrDesc]
    73  		if found {
    74  			newOutpoints := make([]Outpoint, 0, len(outpoints)-1)
    75  			for _, o := range outpoints {
    76  				if o.Txid != txid {
    77  					newOutpoints = append(newOutpoints, o)
    78  				}
    79  			}
    80  			if len(newOutpoints) > 0 {
    81  				m.addrDescToTx[si.addrDesc] = newOutpoints
    82  			} else {
    83  				delete(m.addrDescToTx, si.addrDesc)
    84  			}
    85  		}
    86  	}
    87  }
    88  
    89  // GetAllEntries returns all mempool entries sorted by fist seen time in descending order
    90  func (m *BaseMempool) GetAllEntries() MempoolTxidEntries {
    91  	i := 0
    92  	m.mux.Lock()
    93  	entries := make(MempoolTxidEntries, len(m.txEntries))
    94  	for txid, entry := range m.txEntries {
    95  		entries[i] = MempoolTxidEntry{
    96  			Txid: txid,
    97  			Time: entry.time,
    98  		}
    99  		i++
   100  	}
   101  	m.mux.Unlock()
   102  	sort.Sort(entries)
   103  	return entries
   104  }
   105  
   106  // GetTransactionTime returns first seen time of a transaction
   107  func (m *BaseMempool) GetTransactionTime(txid string) uint32 {
   108  	m.mux.Lock()
   109  	e, found := m.txEntries[txid]
   110  	m.mux.Unlock()
   111  	if !found {
   112  		return 0
   113  	}
   114  	return e.time
   115  }