github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/portxo/sort.go (about)

     1  package portxo
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"github.com/mit-dci/lit/btcutil/chaincfg/chainhash"
     7  )
     8  
     9  // txoSliceByBip69 is a sortable txo slice - same algo as txsort / BIP69
    10  type TxoSliceByBip69 []*PorTxo
    11  
    12  // Sort utxos just like txins -- Len, Less, Swap
    13  func (s TxoSliceByBip69) Len() int      { return len(s) }
    14  func (s TxoSliceByBip69) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    15  
    16  // outpoint sort; First input hash (reversed / rpc-style), then index.
    17  func (s TxoSliceByBip69) Less(i, j int) bool {
    18  	// Input hashes are the same, so compare the index.
    19  	ihash := s[i].Op.Hash
    20  	jhash := s[j].Op.Hash
    21  	if ihash == jhash {
    22  		return s[i].Op.Index < s[j].Op.Index
    23  	}
    24  	// At this point, the hashes are not equal, so reverse them to
    25  	// big-endian and return the result of the comparison.
    26  	const hashSize = chainhash.HashSize
    27  	for b := 0; b < hashSize/2; b++ {
    28  		ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b]
    29  		jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b]
    30  	}
    31  	return bytes.Compare(ihash[:], jhash[:]) == -1
    32  }
    33  
    34  // txoSliceByAmt is a sortable txo slice.  Sorts by value, and puts unconfirmed last.
    35  // Also has sum functions for calculating balances
    36  type TxoSliceByAmt []*PorTxo
    37  
    38  func (s TxoSliceByAmt) Len() int      { return len(s) }
    39  func (s TxoSliceByAmt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    40  
    41  // height 0 means you are lesser
    42  func (s TxoSliceByAmt) Less(i, j int) bool {
    43  	if s[i].Height == 0 && s[j].Height > 0 {
    44  		return true
    45  	}
    46  	if s[j].Height == 0 && s[i].Height > 0 {
    47  		return false
    48  	}
    49  	return s[i].Value < s[j].Value
    50  }
    51  
    52  func (s TxoSliceByAmt) Sum() int64 {
    53  	var total int64
    54  	for _, txo := range s {
    55  		total += txo.Value
    56  	}
    57  	return total
    58  }
    59  
    60  func (s TxoSliceByAmt) SumWitness(currentHeight int32) int64 {
    61  	var total int64
    62  	for _, txo := range s {
    63  		// check that it's witness,
    64  		// then make sure it's confirmed, and any timeouts have passed
    65  		if txo.Mode&FlagTxoWitness != 0 &&
    66  			txo.Height > 0 && txo.Height+int32(txo.Seq) <= currentHeight {
    67  			total += txo.Value
    68  		}
    69  	}
    70  	return total
    71  }
    72  
    73  // KeyGenSortableSlice is a sortable slice of keygens. Shorter and lower numbers first.
    74  type KeyGenSortableSlice []*KeyGen
    75  
    76  func (s KeyGenSortableSlice) Len() int      { return len(s) }
    77  func (s KeyGenSortableSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    78  
    79  func (s KeyGenSortableSlice) Less(i, j int) bool {
    80  	// first - shorter path is less
    81  	if s[i].Depth < s[j].Depth {
    82  		return true
    83  	}
    84  	if s[i].Depth > s[j].Depth {
    85  		return false
    86  	}
    87  
    88  	// paths are the 	same, iterate and compare
    89  	for x := uint8(0); x < s[i].Depth; x++ {
    90  		if s[i].Step[x] < s[j].Step[x] {
    91  			return true
    92  		}
    93  	}
    94  
    95  	// if we got here, they're exactly the same
    96  	return false
    97  }