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

lightningnetwork / lnd / 12312390362

13 Dec 2024 08:44AM UTC coverage: 57.458% (+8.5%) from 48.92%
12312390362

Pull #9343

github

ellemouton
fn: rework the ContextGuard and add tests

In this commit, the ContextGuard struct is re-worked such that the
context that its new main WithCtx method provides is cancelled in sync
with a parent context being cancelled or with it's quit channel being
cancelled. Tests are added to assert the behaviour. In order for the
close of the quit channel to be consistent with the cancelling of the
derived context, the quit channel _must_ be contained internal to the
ContextGuard so that callers are only able to close the channel via the
exposed Quit method which will then take care to first cancel any
derived context that depend on the quit channel before returning.
Pull Request #9343: fn: expand the ContextGuard and add tests

101853 of 177264 relevant lines covered (57.46%)

24972.93 hits per line

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

97.83
/chanbackup/recover.go
1
package chanbackup
2

3
import (
4
        "net"
5

6
        "github.com/btcsuite/btcd/btcec/v2"
7
        "github.com/lightningnetwork/lnd/channeldb"
8
        "github.com/lightningnetwork/lnd/keychain"
9
        "github.com/lightningnetwork/lnd/lnutils"
10
)
11

12
// ChannelRestorer is an interface that allows the Recover method to map the
13
// set of single channel backups into a set of "channel shells" and store these
14
// persistently on disk. The channel shell should contain all the information
15
// needed to execute the data loss recovery protocol once the channel peer is
16
// connected to.
17
type ChannelRestorer interface {
18
        // RestoreChansFromSingles attempts to map the set of single channel
19
        // backups to channel shells that will be stored persistently. Once
20
        // these shells have been stored on disk, we'll be able to connect to
21
        // the channel peer an execute the data loss recovery protocol.
22
        RestoreChansFromSingles(...Single) error
23
}
24

25
// PeerConnector is an interface that allows the Recover method to connect to
26
// the target node given the set of possible addresses.
27
type PeerConnector interface {
28
        // ConnectPeer attempts to connect to the target node at the set of
29
        // available addresses. Once this method returns with a non-nil error,
30
        // the connector should attempt to persistently connect to the target
31
        // peer in the background as a persistent attempt.
32
        ConnectPeer(node *btcec.PublicKey, addrs []net.Addr) error
33
}
34

35
// Recover attempts to recover the static channel state from a set of static
36
// channel backups. If successfully, the database will be populated with a
37
// series of "shell" channels. These "shell" channels cannot be used to operate
38
// the channel as normal, but instead are meant to be used to enter the data
39
// loss recovery phase, and recover the settled funds within
40
// the channel. In addition a LinkNode will be created for each new peer as
41
// well, in order to expose the addressing information required to locate to
42
// and connect to each peer in order to initiate the recovery protocol.
43
// The number of channels that were successfully restored is returned.
44
func Recover(backups []Single, restorer ChannelRestorer,
45
        peerConnector PeerConnector) (int, error) {
6✔
46

6✔
47
        var numRestored int
6✔
48
        for i, backup := range backups {
30✔
49
                log.Infof("Restoring ChannelPoint(%v) to disk: ",
24✔
50
                        backup.FundingOutpoint)
24✔
51

24✔
52
                err := restorer.RestoreChansFromSingles(backup)
24✔
53

24✔
54
                // If a channel is already present in the channel DB, we can
24✔
55
                // just continue. No reason to fail a whole set of multi backups
24✔
56
                // for example. This allows resume of a restore in case another
24✔
57
                // error happens.
24✔
58
                if err == channeldb.ErrChanAlreadyExists {
24✔
59
                        continue
×
60
                }
61
                if err != nil {
26✔
62
                        return numRestored, err
2✔
63
                }
2✔
64

65
                numRestored++
22✔
66
                log.Infof("Attempting to connect to node=%x (addrs=%v) to "+
22✔
67
                        "restore ChannelPoint(%v)",
22✔
68
                        backup.RemoteNodePub.SerializeCompressed(),
22✔
69
                        lnutils.SpewLogClosure(backups[i].Addresses),
22✔
70
                        backup.FundingOutpoint)
22✔
71

22✔
72
                err = peerConnector.ConnectPeer(
22✔
73
                        backup.RemoteNodePub, backup.Addresses,
22✔
74
                )
22✔
75
                if err != nil {
24✔
76
                        return numRestored, err
2✔
77
                }
2✔
78

79
                // TODO(roasbeef): to handle case where node has changed addrs,
80
                // need to subscribe to new updates for target node pub to
81
                // attempt to connect to other addrs
82
                //
83
                //  * just to to fresh w/ call to node addrs and de-dup?
84
        }
85

86
        return numRestored, nil
2✔
87
}
88

89
// TODO(roasbeef): more specific keychain interface?
90

91
// UnpackAndRecoverSingles is a one-shot method, that given a set of packed
92
// single channel backups, will restore the channel state to a channel shell,
93
// and also reach out to connect to any of the known node addresses for that
94
// channel. It is assumes that after this method exists, if a connection was
95
// established, then the PeerConnector will continue to attempt to re-establish
96
// a persistent connection in the background. The number of channels that were
97
// successfully restored is returned.
98
func UnpackAndRecoverSingles(singles PackedSingles,
99
        keyChain keychain.KeyRing, restorer ChannelRestorer,
100
        peerConnector PeerConnector) (int, error) {
4✔
101

4✔
102
        chanBackups, err := singles.Unpack(keyChain)
4✔
103
        if err != nil {
5✔
104
                return 0, err
1✔
105
        }
1✔
106

107
        return Recover(chanBackups, restorer, peerConnector)
3✔
108
}
109

110
// UnpackAndRecoverMulti is a one-shot method, that given a set of packed
111
// multi-channel backups, will restore the channel states to channel shells,
112
// and also reach out to connect to any of the known node addresses for that
113
// channel. It is assumes that after this method exists, if a connection was
114
// established, then the PeerConnector will continue to attempt to re-establish
115
// a persistent connection in the background. The number of channels that were
116
// successfully restored is returned.
117
func UnpackAndRecoverMulti(packedMulti PackedMulti,
118
        keyChain keychain.KeyRing, restorer ChannelRestorer,
119
        peerConnector PeerConnector) (int, error) {
4✔
120

4✔
121
        chanBackups, err := packedMulti.Unpack(keyChain)
4✔
122
        if err != nil {
5✔
123
                return 0, err
1✔
124
        }
1✔
125

126
        return Recover(chanBackups.StaticBackups, restorer, peerConnector)
3✔
127
}
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