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

lightningnetwork / lnd / 15249422085

26 May 2025 08:11AM UTC coverage: 57.977% (-11.0%) from 69.015%
15249422085

push

github

web-flow
Merge pull request #9853 from lightningnetwork/elle-graphSQL8-prep

graph/db: init SQLStore caches and batch schedulers

9 of 34 new or added lines in 4 files covered. (26.47%)

29283 existing lines in 458 files now uncovered.

96475 of 166402 relevant lines covered (57.98%)

1.22 hits per line

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

78.95
/chanbackup/backup.go
1
package chanbackup
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/wire"
7
        "github.com/lightningnetwork/lnd/channeldb"
8
        "github.com/lightningnetwork/lnd/fn/v2"
9
)
10

11
// LiveChannelSource is an interface that allows us to query for the set of
12
// live channels. A live channel is one that is open, and has not had a
13
// commitment transaction broadcast.
14
type LiveChannelSource interface {
15
        // FetchAllChannels returns all known live channels.
16
        FetchAllChannels() ([]*channeldb.OpenChannel, error)
17

18
        // FetchChannel attempts to locate a live channel identified by the
19
        // passed chanPoint. Optionally an existing db tx can be supplied.
20
        FetchChannel(chanPoint wire.OutPoint) (*channeldb.OpenChannel, error)
21
}
22

23
// assembleChanBackup attempts to assemble a static channel backup for the
24
// passed open channel. The backup includes all information required to restore
25
// the channel, as well as addressing information so we can find the peer and
26
// reconnect to them to initiate the protocol.
27
func assembleChanBackup(addrSource channeldb.AddrSource,
28
        openChan *channeldb.OpenChannel) (*Single, error) {
2✔
29

2✔
30
        log.Debugf("Crafting backup for ChannelPoint(%v)",
2✔
31
                openChan.FundingOutpoint)
2✔
32

2✔
33
        // First, we'll query the channel source to obtain all the addresses
2✔
34
        // that are associated with the peer for this channel.
2✔
35
        known, nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
2✔
36
        if err != nil {
2✔
37
                return nil, err
×
38
        }
×
39
        if !known {
2✔
UNCOV
40
                return nil, fmt.Errorf("node unknown by address source")
×
UNCOV
41
        }
×
42

43
        single := NewSingle(openChan, nodeAddrs)
2✔
44

2✔
45
        return &single, nil
2✔
46
}
47

48
// buildCloseTxInputs generates inputs needed to force close a channel from
49
// an open channel. Anyone having these inputs and the signer, can sign the
50
// force closure transaction. Warning! If the channel state updates, an attempt
51
// to close the channel using this method with outdated CloseTxInputs can result
52
// in loss of funds! This may happen if an outdated channel backup is attempted
53
// to be used to force close the channel.
54
func buildCloseTxInputs(
55
        targetChan *channeldb.OpenChannel) fn.Option[CloseTxInputs] {
2✔
56

2✔
57
        log.Debugf("Crafting CloseTxInputs for ChannelPoint(%v)",
2✔
58
                targetChan.FundingOutpoint)
2✔
59

2✔
60
        localCommit := targetChan.LocalCommitment
2✔
61

2✔
62
        if localCommit.CommitTx == nil {
4✔
63
                log.Infof("CommitTx is nil for ChannelPoint(%v), "+
2✔
64
                        "skipping CloseTxInputs. This is possible when "+
2✔
65
                        "DLP is active.", targetChan.FundingOutpoint)
2✔
66

2✔
67
                return fn.None[CloseTxInputs]()
2✔
68
        }
2✔
69

70
        // We need unsigned force close tx and the counterparty's signature.
71
        inputs := CloseTxInputs{
2✔
72
                CommitTx:  localCommit.CommitTx,
2✔
73
                CommitSig: localCommit.CommitSig,
2✔
74
        }
2✔
75

2✔
76
        // In case of a taproot channel, commit height is needed as well to
2✔
77
        // produce verification nonce for the taproot channel using shachain.
2✔
78
        if targetChan.ChanType.IsTaproot() {
4✔
79
                inputs.CommitHeight = localCommit.CommitHeight
2✔
80
        }
2✔
81

82
        // In case of a custom taproot channel, TapscriptRoot is needed as well.
83
        if targetChan.ChanType.HasTapscriptRoot() {
2✔
UNCOV
84
                inputs.TapscriptRoot = targetChan.TapscriptRoot
×
UNCOV
85
        }
×
86

87
        return fn.Some(inputs)
2✔
88
}
89

90
// FetchBackupForChan attempts to create a plaintext static channel backup for
91
// the target channel identified by its channel point. If we're unable to find
92
// the target channel, then an error will be returned.
93
func FetchBackupForChan(chanPoint wire.OutPoint, chanSource LiveChannelSource,
94
        addrSource channeldb.AddrSource) (*Single, error) {
2✔
95

2✔
96
        // First, we'll query the channel source to see if the channel is known
2✔
97
        // and open within the database.
2✔
98
        targetChan, err := chanSource.FetchChannel(chanPoint)
2✔
99
        if err != nil {
2✔
UNCOV
100
                // If we can't find the channel, then we return with an error,
×
UNCOV
101
                // as we have nothing to  backup.
×
UNCOV
102
                return nil, fmt.Errorf("unable to find target channel")
×
UNCOV
103
        }
×
104

105
        // Once we have the target channel, we can assemble the backup using
106
        // the source to obtain any extra information that we may need.
107
        staticChanBackup, err := assembleChanBackup(addrSource, targetChan)
2✔
108
        if err != nil {
2✔
UNCOV
109
                return nil, fmt.Errorf("unable to create chan backup: %w", err)
×
UNCOV
110
        }
×
111

112
        return staticChanBackup, nil
2✔
113
}
114

115
// FetchStaticChanBackups will return a plaintext static channel back up for
116
// all known active/open channels within the passed channel source.
117
func FetchStaticChanBackups(chanSource LiveChannelSource,
118
        addrSource channeldb.AddrSource) ([]Single, error) {
2✔
119

2✔
120
        // First, we'll query the backup source for information concerning all
2✔
121
        // currently open and available channels.
2✔
122
        openChans, err := chanSource.FetchAllChannels()
2✔
123
        if err != nil {
2✔
UNCOV
124
                return nil, err
×
UNCOV
125
        }
×
126

127
        // Now that we have all the channels, we'll use the chanSource to
128
        // obtain any auxiliary information we need to craft a backup for each
129
        // channel.
130
        staticChanBackups := make([]Single, 0, len(openChans))
2✔
131
        for _, openChan := range openChans {
4✔
132
                chanBackup, err := assembleChanBackup(addrSource, openChan)
2✔
133
                if err != nil {
2✔
UNCOV
134
                        return nil, err
×
UNCOV
135
                }
×
136

137
                staticChanBackups = append(staticChanBackups, *chanBackup)
2✔
138
        }
139

140
        return staticChanBackups, nil
2✔
141
}
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