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

lightningnetwork / lnd / 13586005509

28 Feb 2025 10:14AM UTC coverage: 68.629% (+9.9%) from 58.77%
13586005509

Pull #9521

github

web-flow
Merge 37d3a70a5 into 8532955b3
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

129950 of 189351 relevant lines covered (68.63%)

23726.46 hits per line

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

97.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) {
4,160✔
26
        if len(tx.TxOut) != len(cltvs) {
4,160✔
27
                panic("output and cltv list size mismatch")
×
28
        }
29

30
        sort.Sort(sortableInputSlice(tx.TxIn))
4,160✔
31
        sort.Sort(sortableCommitOutputSlice{tx.TxOut, cltvs})
4,160✔
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) }
4,160✔
42

43
// Swap exchanges the position of inputs i and j.
44
//
45
// NOTE: Part of the sort.Interface interface.
46
func (s sortableInputSlice) Swap(i, j int) {
2✔
47
        s[i], s[j] = s[j], s[i]
2✔
48
}
2✔
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.
55
func (s sortableInputSlice) Less(i, j int) bool {
3✔
56
        // Input hashes are the same, so compare the index.
3✔
57
        ihash := s[i].PreviousOutPoint.Hash
3✔
58
        jhash := s[j].PreviousOutPoint.Hash
3✔
59
        if ihash == jhash {
5✔
60
                return s[i].PreviousOutPoint.Index < s[j].PreviousOutPoint.Index
2✔
61
        }
2✔
62

63
        // At this point, the hashes are not equal, so reverse them to
64
        // big-endian and return the result of the comparison.
65
        const hashSize = chainhash.HashSize
1✔
66
        for b := 0; b < hashSize/2; b++ {
17✔
67
                ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b]
16✔
68
                jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b]
16✔
69
        }
16✔
70
        return bytes.Compare(ihash[:], jhash[:]) == -1
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 {
4,160✔
85
        return len(s.txouts)
4,160✔
86
}
4,160✔
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) {
23,326✔
93
        s.txouts[i], s.txouts[j] = s.txouts[j], s.txouts[i]
23,326✔
94
        s.cltvs[i], s.cltvs[j] = s.cltvs[j], s.cltvs[i]
23,326✔
95
}
23,326✔
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 {
41,547✔
102
        outi, outj := s.txouts[i], s.txouts[j]
41,547✔
103

41,547✔
104
        if outi.Value != outj.Value {
53,417✔
105
                return outi.Value < outj.Value
11,870✔
106
        }
11,870✔
107

108
        pkScriptCmp := bytes.Compare(outi.PkScript, outj.PkScript)
29,680✔
109
        if pkScriptCmp != 0 {
59,292✔
110
                return pkScriptCmp < 0
29,612✔
111
        }
29,612✔
112

113
        return s.cltvs[i] < s.cltvs[j]
71✔
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