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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

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

71.74
/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) {
3✔
46

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

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

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

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

3✔
72
                err = peerConnector.ConnectPeer(
3✔
73
                        backup.RemoteNodePub, backup.Addresses,
3✔
74
                )
3✔
75
                if err != nil {
3✔
UNCOV
76
                        return numRestored, err
×
UNCOV
77
                }
×
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
3✔
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,
UNCOV
100
        peerConnector PeerConnector) (int, error) {
×
UNCOV
101

×
UNCOV
102
        chanBackups, err := singles.Unpack(keyChain)
×
UNCOV
103
        if err != nil {
×
UNCOV
104
                return 0, err
×
UNCOV
105
        }
×
106

UNCOV
107
        return Recover(chanBackups, restorer, peerConnector)
×
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) {
3✔
120

3✔
121
        chanBackups, err := packedMulti.Unpack(keyChain)
3✔
122
        if err != nil {
3✔
UNCOV
123
                return 0, err
×
UNCOV
124
        }
×
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