• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.5
/lnwallet/commit_sort.go
1
package lnwallet
2

3
import (
4
        "bytes"
5
        "sort"
6

7
        "github.com/btcsuite/btcd/chaincfg/chainhash"
8
        "github.com/btcsuite/btcd/wire"
9
)
10

11
// InPlaceCommitSort performs an in-place sort of a commitment transaction,
12
// given an unsorted transaction and a list of CLTV values for the HTLCs.
13
//
14
// The sort applied is a modified BIP69 sort, that uses the CLTV values of HTLCs
15
// as a tie breaker in case two HTLC outputs have an identical amount and
16
// pkscript. The pkscripts can be the same if they share the same payment hash,
17
// but since the CLTV is enforced via the nLockTime of the second-layer
18
// transactions, the script does not directly commit to them. Instead, the CLTVs
19
// must be supplied separately to act as a tie-breaker, otherwise we may produce
20
// invalid HTLC signatures if the receiver produces an alternative ordering
21
// during verification.
22
//
23
// NOTE: Commitment outputs should have a 0 CLTV corresponding to their index on
24
// the unsorted commitment transaction.
25
func InPlaceCommitSort(tx *wire.MsgTx, cltvs []uint32) {
3✔
26
        if len(tx.TxOut) != len(cltvs) {
3✔
27
                panic("output and cltv list size mismatch")
×
28
        }
29

30
        sort.Sort(sortableInputSlice(tx.TxIn))
3✔
31
        sort.Sort(sortableCommitOutputSlice{tx.TxOut, cltvs})
3✔
32
}
33

34
// sortableInputSlice is a slice of transaction inputs that supports sorting via
35
// BIP69.
36
type sortableInputSlice []*wire.TxIn
37

38
// Len returns the length of the sortableInputSlice.
39
//
40
// NOTE: Part of the sort.Interface interface.
41
func (s sortableInputSlice) Len() int { return len(s) }
3✔
42

43
// Swap exchanges the position of inputs i and j.
44
//
45
// NOTE: Part of the sort.Interface interface.
UNCOV
46
func (s sortableInputSlice) Swap(i, j int) {
×
UNCOV
47
        s[i], s[j] = s[j], s[i]
×
UNCOV
48
}
×
49

50
// Less is the BIP69 input comparison function. The sort is first applied on
51
// input hash (reversed / rpc-style), then index. This logic is copied from
52
// btcutil/txsort.
53
//
54
// NOTE: Part of the sort.Interface interface.
UNCOV
55
func (s sortableInputSlice) Less(i, j int) bool {
×
UNCOV
56
        // Input hashes are the same, so compare the index.
×
UNCOV
57
        ihash := s[i].PreviousOutPoint.Hash
×
UNCOV
58
        jhash := s[j].PreviousOutPoint.Hash
×
UNCOV
59
        if ihash == jhash {
×
UNCOV
60
                return s[i].PreviousOutPoint.Index < s[j].PreviousOutPoint.Index
×
UNCOV
61
        }
×
62

63
        // At this point, the hashes are not equal, so reverse them to
64
        // big-endian and return the result of the comparison.
UNCOV
65
        const hashSize = chainhash.HashSize
×
UNCOV
66
        for b := 0; b < hashSize/2; b++ {
×
UNCOV
67
                ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b]
×
UNCOV
68
                jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b]
×
UNCOV
69
        }
×
UNCOV
70
        return bytes.Compare(ihash[:], jhash[:]) == -1
×
71
}
72

73
// sortableCommitOutputSlice is a slice of transaction outputs on a commitment
74
// transaction and the corresponding CLTV values of any HTLCs. Commitment
75
// outputs should have a CLTV of 0 and the same index in cltvs.
76
type sortableCommitOutputSlice struct {
77
        txouts []*wire.TxOut
78
        cltvs  []uint32
79
}
80

81
// Len returns the length of the sortableCommitOutputSlice.
82
//
83
// NOTE: Part of the sort.Interface interface.
84
func (s sortableCommitOutputSlice) Len() int {
3✔
85
        return len(s.txouts)
3✔
86
}
3✔
87

88
// Swap exchanges the position of outputs i and j, as well as their
89
// corresponding CLTV values.
90
//
91
// NOTE: Part of the sort.Interface interface.
92
func (s sortableCommitOutputSlice) Swap(i, j int) {
3✔
93
        s.txouts[i], s.txouts[j] = s.txouts[j], s.txouts[i]
3✔
94
        s.cltvs[i], s.cltvs[j] = s.cltvs[j], s.cltvs[i]
3✔
95
}
3✔
96

97
// Less is a modified BIP69 output comparison, that sorts based on value, then
98
// pkscript, then CLTV value.
99
//
100
// NOTE: Part of the sort.Interface interface.
101
func (s sortableCommitOutputSlice) Less(i, j int) bool {
3✔
102
        outi, outj := s.txouts[i], s.txouts[j]
3✔
103

3✔
104
        if outi.Value != outj.Value {
6✔
105
                return outi.Value < outj.Value
3✔
106
        }
3✔
107

108
        pkScriptCmp := bytes.Compare(outi.PkScript, outj.PkScript)
3✔
109
        if pkScriptCmp != 0 {
6✔
110
                return pkScriptCmp < 0
3✔
111
        }
3✔
112

113
        return s.cltvs[i] < s.cltvs[j]
3✔
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc