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

lightningnetwork / lnd / 15606538456

12 Jun 2025 09:14AM UTC coverage: 67.414% (+9.1%) from 58.333%
15606538456

Pull #9932

github

web-flow
Merge 25e652669 into 35102e7c3
Pull Request #9932: [draft] graph/db+sqldb: graph store SQL implementation + migration

23 of 3319 new or added lines in 7 files covered. (0.69%)

39 existing lines in 8 files now uncovered.

134459 of 199453 relevant lines covered (67.41%)

21872.74 hits per line

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

91.59
/witness_beacon.go
1
package lnd
2

3
import (
4
        "errors"
5
        "sync"
6

7
        "github.com/lightningnetwork/lnd/channeldb"
8
        "github.com/lightningnetwork/lnd/contractcourt"
9
        "github.com/lightningnetwork/lnd/graph/db/models"
10
        "github.com/lightningnetwork/lnd/htlcswitch"
11
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
12
        "github.com/lightningnetwork/lnd/lntypes"
13
        "github.com/lightningnetwork/lnd/lnwire"
14
)
15

16
// preimageSubscriber reprints an active subscription to be notified once the
17
// daemon discovers new preimages, either on chain or off-chain.
18
type preimageSubscriber struct {
19
        updateChan chan lntypes.Preimage
20

21
        quit chan struct{}
22
}
23

24
type witnessCache interface {
25
        // LookupSha256Witness attempts to lookup the preimage for a sha256
26
        // hash. If the witness isn't found, ErrNoWitnesses will be returned.
27
        LookupSha256Witness(hash lntypes.Hash) (lntypes.Preimage, error)
28

29
        // AddSha256Witnesses adds a batch of new sha256 preimages into the
30
        // witness cache. This is an alias for AddWitnesses that uses
31
        // Sha256HashWitness as the preimages' witness type.
32
        AddSha256Witnesses(preimages ...lntypes.Preimage) error
33
}
34

35
// preimageBeacon is an implementation of the contractcourt.WitnessBeacon
36
// interface, and the lnwallet.PreimageCache interface. This implementation is
37
// concerned with a single witness type: sha256 hahsh preimages.
38
type preimageBeacon struct {
39
        sync.RWMutex
40

41
        wCache witnessCache
42

43
        clientCounter uint64
44
        subscribers   map[uint64]*preimageSubscriber
45

46
        interceptor func(htlcswitch.InterceptedForward) error
47
}
48

49
func newPreimageBeacon(wCache witnessCache,
50
        interceptor func(htlcswitch.InterceptedForward) error) *preimageBeacon {
4✔
51

4✔
52
        return &preimageBeacon{
4✔
53
                wCache:      wCache,
4✔
54
                interceptor: interceptor,
4✔
55
                subscribers: make(map[uint64]*preimageSubscriber),
4✔
56
        }
4✔
57
}
4✔
58

59
// SubscribeUpdates returns a channel that will be sent upon *each* time a new
60
// preimage is discovered.
61
func (p *preimageBeacon) SubscribeUpdates(
62
        chanID lnwire.ShortChannelID, htlc *channeldb.HTLC,
63
        payload *hop.Payload,
64
        nextHopOnionBlob []byte) (*contractcourt.WitnessSubscription, error) {
4✔
65

4✔
66
        p.Lock()
4✔
67
        defer p.Unlock()
4✔
68

4✔
69
        clientID := p.clientCounter
4✔
70
        client := &preimageSubscriber{
4✔
71
                updateChan: make(chan lntypes.Preimage, 10),
4✔
72
                quit:       make(chan struct{}),
4✔
73
        }
4✔
74

4✔
75
        p.subscribers[p.clientCounter] = client
4✔
76

4✔
77
        p.clientCounter++
4✔
78

4✔
79
        srvrLog.Debugf("Creating new witness beacon subscriber, id=%v",
4✔
80
                p.clientCounter)
4✔
81

4✔
82
        sub := &contractcourt.WitnessSubscription{
4✔
83
                WitnessUpdates: client.updateChan,
4✔
84
                CancelSubscription: func() {
8✔
85
                        p.Lock()
4✔
86
                        defer p.Unlock()
4✔
87

4✔
88
                        delete(p.subscribers, clientID)
4✔
89

4✔
90
                        close(client.quit)
4✔
91
                },
4✔
92
        }
93

94
        // Notify the htlc interceptor. There may be a client connected
95
        // and willing to supply a preimage.
96
        packet := &htlcswitch.InterceptedPacket{
4✔
97
                Hash:           htlc.RHash,
4✔
98
                IncomingExpiry: htlc.RefundTimeout,
4✔
99
                IncomingAmount: htlc.Amt,
4✔
100
                IncomingCircuit: models.CircuitKey{
4✔
101
                        ChanID: chanID,
4✔
102
                        HtlcID: htlc.HtlcIndex,
4✔
103
                },
4✔
104
                OutgoingChanID:       payload.FwdInfo.NextHop,
4✔
105
                OutgoingExpiry:       payload.FwdInfo.OutgoingCTLV,
4✔
106
                OutgoingAmount:       payload.FwdInfo.AmountToForward,
4✔
107
                InOnionCustomRecords: payload.CustomRecords(),
4✔
108
                InWireCustomRecords:  htlc.CustomRecords,
4✔
109
        }
4✔
110
        copy(packet.OnionBlob[:], nextHopOnionBlob)
4✔
111

4✔
112
        fwd := newInterceptedForward(packet, p)
4✔
113

4✔
114
        err := p.interceptor(fwd)
4✔
115
        if err != nil {
4✔
116
                return nil, err
×
117
        }
×
118

119
        return sub, nil
4✔
120
}
121

122
// LookupPreimage attempts to lookup a preimage in the global cache.  True is
123
// returned for the second argument if the preimage is found.
124
func (p *preimageBeacon) LookupPreimage(
125
        payHash lntypes.Hash) (lntypes.Preimage, bool) {
3✔
126

3✔
127
        p.RLock()
3✔
128
        defer p.RUnlock()
3✔
129

3✔
130
        // Otherwise, we'll perform a final check using the witness cache.
3✔
131
        preimage, err := p.wCache.LookupSha256Witness(payHash)
3✔
132
        if errors.Is(err, channeldb.ErrNoWitnesses) {
6✔
133
                ltndLog.Debugf("No witness for payment %v", payHash)
3✔
134
                return lntypes.Preimage{}, false
3✔
135
        }
3✔
136

137
        if err != nil {
3✔
138
                ltndLog.Errorf("Unable to lookup witness: %v", err)
×
139
                return lntypes.Preimage{}, false
×
140
        }
×
141

142
        return preimage, true
3✔
143
}
144

145
// AddPreimages adds a batch of newly discovered preimages to the global cache,
146
// and also signals any subscribers of the newly discovered witness.
147
func (p *preimageBeacon) AddPreimages(preimages ...lntypes.Preimage) error {
4✔
148
        // Exit early if no preimages are presented.
4✔
149
        if len(preimages) == 0 {
7✔
150
                return nil
3✔
151
        }
3✔
152

153
        // Copy the preimages to ensure the backing area can't be modified by
154
        // the caller when delivering notifications.
155
        preimageCopies := make([]lntypes.Preimage, 0, len(preimages))
4✔
156
        for _, preimage := range preimages {
8✔
157
                srvrLog.Infof("Adding preimage=%v to witness cache for %v",
4✔
158
                        preimage, preimage.Hash())
4✔
159

4✔
160
                preimageCopies = append(preimageCopies, preimage)
4✔
161
        }
4✔
162

163
        // First, we'll add the witness to the decaying witness cache.
164
        err := p.wCache.AddSha256Witnesses(preimages...)
4✔
165
        if err != nil {
4✔
166
                return err
×
167
        }
×
168

169
        p.Lock()
4✔
170
        defer p.Unlock()
4✔
171

4✔
172
        // With the preimage added to our state, we'll now send a new
4✔
173
        // notification to all subscribers.
4✔
174
        for _, client := range p.subscribers {
8✔
175
                go func(c *preimageSubscriber) {
8✔
176
                        for _, preimage := range preimageCopies {
8✔
177
                                select {
4✔
178
                                case c.updateChan <- preimage:
4✔
UNCOV
179
                                case <-c.quit:
×
UNCOV
180
                                        return
×
181
                                }
182
                        }
183
                }(client)
184
        }
185

186
        srvrLog.Debugf("Added %d preimage(s) to witness cache",
4✔
187
                len(preimageCopies))
4✔
188

4✔
189
        return nil
4✔
190
}
191

192
var _ contractcourt.WitnessBeacon = (*preimageBeacon)(nil)
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