github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/sequencer/efficiencylist.go (about)

     1  package sequencer
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"sync"
     7  
     8  	"github.com/0xPolygon/supernets2-node/log"
     9  )
    10  
    11  // efficiencyList represents a list of tx sorted by efficiency
    12  type efficiencyList struct {
    13  	list   map[string]*TxTracker
    14  	sorted []*TxTracker
    15  	mutex  sync.Mutex
    16  }
    17  
    18  // newEfficiencyList creates and init an efficiencyList
    19  func newEfficiencyList() *efficiencyList {
    20  	return &efficiencyList{
    21  		list:   make(map[string]*TxTracker),
    22  		sorted: []*TxTracker{},
    23  	}
    24  }
    25  
    26  // add adds a tx to the efficiencyList
    27  func (e *efficiencyList) add(tx *TxTracker) bool {
    28  	e.mutex.Lock()
    29  	defer e.mutex.Unlock()
    30  
    31  	if _, found := e.list[tx.HashStr]; !found {
    32  		e.list[tx.HashStr] = tx
    33  		e.addSort(tx)
    34  		return true
    35  	}
    36  	return false
    37  }
    38  
    39  // delete deletes the tx from the efficiencyList
    40  func (e *efficiencyList) delete(tx *TxTracker) bool {
    41  	e.mutex.Lock()
    42  	defer e.mutex.Unlock()
    43  
    44  	if tx, found := e.list[tx.HashStr]; found {
    45  		sLen := len(e.sorted)
    46  		i := sort.Search(sLen, func(i int) bool {
    47  			return e.isGreaterThan(tx, e.list[e.sorted[i].HashStr])
    48  		})
    49  
    50  		if (e.sorted[i].HashStr != tx.HashStr) || i == sLen {
    51  			log.Errorf("Error deleting tx from efficiencyList: %s", tx.HashStr)
    52  			return false
    53  		}
    54  
    55  		delete(e.list, tx.HashStr)
    56  
    57  		copy(e.sorted[i:], e.sorted[i+1:])
    58  		e.sorted[sLen-1] = nil
    59  		e.sorted = e.sorted[:sLen-1]
    60  
    61  		return true
    62  	}
    63  	return false
    64  }
    65  
    66  // getByIndex retrieves the tx at the i position in the sorted EfficiencyList
    67  func (e *efficiencyList) getByIndex(i int) *TxTracker {
    68  	e.mutex.Lock()
    69  	defer e.mutex.Unlock()
    70  
    71  	tx := e.sorted[i]
    72  
    73  	return tx
    74  }
    75  
    76  // len returns the length of the EfficiencyList
    77  func (e *efficiencyList) len() int {
    78  	e.mutex.Lock()
    79  	defer e.mutex.Unlock()
    80  
    81  	l := len(e.sorted)
    82  
    83  	return l
    84  }
    85  
    86  // print prints the contents of the EfficiencyList
    87  func (e *efficiencyList) Print() {
    88  	e.mutex.Lock()
    89  	defer e.mutex.Unlock()
    90  
    91  	fmt.Println("Len: ", len(e.sorted))
    92  	for _, txi := range e.sorted {
    93  		fmt.Printf("Hash=%s, efficiency=%f\n", txi.HashStr, txi.Efficiency)
    94  	}
    95  }
    96  
    97  // addSort adds the tx to the EfficiencyList in a sorted way
    98  func (e *efficiencyList) addSort(tx *TxTracker) {
    99  	i := sort.Search(len(e.sorted), func(i int) bool {
   100  		return e.isGreaterThan(tx, e.list[e.sorted[i].HashStr])
   101  	})
   102  
   103  	e.sorted = append(e.sorted, nil)
   104  	copy(e.sorted[i+1:], e.sorted[i:])
   105  	e.sorted[i] = tx
   106  	log.Infof("Added tx(%s) to efficiencyList. With efficiency(%f) at index(%d) from total(%d)", tx.HashStr, tx.Efficiency, i, len(e.sorted))
   107  }
   108  
   109  // isGreaterThan returns true if the tx1 has best efficiency than tx2
   110  func (e *efficiencyList) isGreaterThan(tx1 *TxTracker, tx2 *TxTracker) bool {
   111  	if tx1.Efficiency > tx2.Efficiency {
   112  		return true
   113  	} else if tx1.Efficiency == tx2.Efficiency {
   114  		return tx1.HashStr >= tx2.HashStr
   115  	} else {
   116  		return false
   117  	}
   118  }
   119  
   120  // GetSorted returns the sorted list of tx
   121  func (e *efficiencyList) GetSorted() []*TxTracker {
   122  	e.mutex.Lock()
   123  	defer e.mutex.Unlock()
   124  
   125  	return e.sorted
   126  }