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

lightningnetwork / lnd / 15602296443

12 Jun 2025 05:19AM UTC coverage: 57.49% (-0.8%) from 58.333%
15602296443

Pull #9932

github

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

7 of 2587 new or added lines in 6 files covered. (0.27%)

240 existing lines in 11 files now uncovered.

97770 of 170065 relevant lines covered (57.49%)

1.78 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 {
3✔
51

3✔
52
        return &preimageBeacon{
3✔
53
                wCache:      wCache,
3✔
54
                interceptor: interceptor,
3✔
55
                subscribers: make(map[uint64]*preimageSubscriber),
3✔
56
        }
3✔
57
}
3✔
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) {
3✔
65

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

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

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

3✔
77
        p.clientCounter++
3✔
78

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

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

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

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

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

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

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

119
        return sub, nil
3✔
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 {
3✔
148
        // Exit early if no preimages are presented.
3✔
149
        if len(preimages) == 0 {
6✔
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))
3✔
156
        for _, preimage := range preimages {
6✔
157
                srvrLog.Infof("Adding preimage=%v to witness cache for %v",
3✔
158
                        preimage, preimage.Hash())
3✔
159

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

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

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

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

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

3✔
189
        return nil
3✔
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