• 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

59.32
/batch/batch.go
1
package batch
2

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

7
        "github.com/lightningnetwork/lnd/kvdb"
8
        "github.com/lightningnetwork/lnd/sqldb"
9
)
10

11
// errSolo is a sentinel error indicating that the requester should re-run the
12
// operation in isolation.
13
var errSolo = errors.New(
14
        "batch function returned an error and should be re-run solo",
15
)
16

17
type request struct {
18
        *Request
19
        errChan chan error
20
}
21

22
type batch struct {
23
        db     kvdb.Backend
24
        start  sync.Once
25
        reqs   []*request
26
        clear  func(b *batch)
27
        locker sync.Locker
28
}
29

30
// trigger is the entry point for the batch and ensures that run is started at
31
// most once.
32
func (b *batch) trigger() {
3✔
33
        b.start.Do(b.run)
3✔
34
}
3✔
35

36
// run executes the current batch of requests. If any individual requests fail
37
// alongside others they will be retried by the caller.
38
func (b *batch) run() {
3✔
39
        // Clear the batch from its scheduler, ensuring that no new requests are
3✔
40
        // added to this batch.
3✔
41
        b.clear(b)
3✔
42

3✔
43
        // If a cache lock was provided, hold it until the this method returns.
3✔
44
        // This is critical for ensuring external consistency of the operation,
3✔
45
        // so that caches don't get out of sync with the on disk state.
3✔
46
        if b.locker != nil {
6✔
47
                b.locker.Lock()
3✔
48
                defer b.locker.Unlock()
3✔
49
        }
3✔
50

51
        // Apply the batch until a subset succeeds or all of them fail. Requests
52
        // that fail will be retried individually.
53
        for len(b.reqs) > 0 {
6✔
54
                var failIdx = -1
3✔
55
                err := kvdb.Update(b.db, func(tx kvdb.RwTx) error {
6✔
56
                        for i, req := range b.reqs {
6✔
57
                                err := req.Update(tx)
3✔
58
                                if err != nil {
3✔
UNCOV
59
                                        // If we get a serialization error, we
×
UNCOV
60
                                        // want the underlying SQL retry
×
UNCOV
61
                                        // mechanism to retry the entire batch.
×
UNCOV
62
                                        // Otherwise, we can succeed in an
×
UNCOV
63
                                        // sqldb retry and still re-execute the
×
UNCOV
64
                                        // failing request individually.
×
UNCOV
65
                                        dbErr := sqldb.MapSQLError(err)
×
UNCOV
66
                                        if !sqldb.IsSerializationError(dbErr) {
×
UNCOV
67
                                                failIdx = i
×
UNCOV
68

×
UNCOV
69
                                                return err
×
UNCOV
70
                                        }
×
71

UNCOV
72
                                        return dbErr
×
73
                                }
74
                        }
75
                        return nil
3✔
76
                }, func() {
3✔
77
                        for _, req := range b.reqs {
6✔
78
                                if req.Reset != nil {
6✔
79
                                        req.Reset()
3✔
80
                                }
3✔
81
                        }
82
                })
83

84
                // If a request's Update failed, extract it and re-run the
85
                // batch. The removed request will be retried individually by
86
                // the caller.
87
                if failIdx >= 0 {
3✔
UNCOV
88
                        req := b.reqs[failIdx]
×
UNCOV
89

×
UNCOV
90
                        // It's safe to shorten b.reqs here because the
×
UNCOV
91
                        // scheduler's batch no longer points to us.
×
UNCOV
92
                        b.reqs[failIdx] = b.reqs[len(b.reqs)-1]
×
UNCOV
93
                        b.reqs = b.reqs[:len(b.reqs)-1]
×
UNCOV
94

×
UNCOV
95
                        // Tell the submitter re-run it solo, continue with the
×
UNCOV
96
                        // rest of the batch.
×
UNCOV
97
                        req.errChan <- errSolo
×
UNCOV
98
                        continue
×
99
                }
100

101
                // None of the remaining requests failed, process the errors
102
                // using each request's OnCommit closure and return the error
103
                // to the requester. If no OnCommit closure is provided, simply
104
                // return the error directly.
105
                for _, req := range b.reqs {
6✔
106
                        if req.OnCommit != nil {
6✔
107
                                req.errChan <- req.OnCommit(err)
3✔
108
                        } else {
6✔
109
                                req.errChan <- err
3✔
110
                        }
3✔
111
                }
112

113
                return
3✔
114
        }
115
}
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

© 2026 Coveralls, Inc