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

lightningnetwork / lnd / 12879602034

21 Jan 2025 03:26AM UTC coverage: 49.413% (-9.3%) from 58.72%
12879602034

Pull #9430

github

Roasbeef
lnwallet: add new NoopAdd payDesc entry type

In this commit, we add a new NoopAdd payDesc entry type. This type is
meant to be used primarily by taproot overlay channels. When we go to
settle this HTLC, rather than credit the settler for the funds, we just
give the funds back to the sender. This results in an add that when
settled, doesn't affect the balance in the channel.

This new HTLC type is intended to be used alongside a push amt, to
ensure the remote party has a non-dust balance from the start. With that
in place, then this new add type can be used for special overlay HTLCs.
Pull Request #9430: lnwallet: add new NoopAdd payDesc entry type

23 of 36 new or added lines in 2 files covered. (63.89%)

26915 existing lines in 431 files now uncovered.

100600 of 203591 relevant lines covered (49.41%)

1.54 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