Skip to content

Commit 51c2f70

Browse files
committed
channeldb: let AddrsForNode indicate if the node was found or not
Before this commit, the `(channeldb.DB).AddrsForNode` method treats the results from the channel db and the graph db slightly differently. It errors out if the channel db is unaware of the node in question but does not error out if the graph is unaware of the node. So this commit changes the logic slightly so that a "node-unknown" error from either backing source is not seen as an error.
1 parent 9537026 commit 51c2f70

File tree

7 files changed

+112
-49
lines changed

7 files changed

+112
-49
lines changed

chanbackup/backup.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ func assembleChanBackup(addrSource channeldb.AddrSource,
3434

3535
// First, we'll query the channel source to obtain all the addresses
3636
// that are associated with the peer for this channel.
37-
nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
37+
known, nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
3838
if err != nil {
3939
return nil, err
4040
}
41+
if !known {
42+
return nil, fmt.Errorf("node unknown by address source")
43+
}
4144

4245
single := NewSingle(openChan, nodeAddrs)
4346

chanbackup/backup_test.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,19 @@ func (m *mockChannelSource) addAddrsForNode(nodePub *btcec.PublicKey, addrs []ne
6262
m.addrs[nodeKey] = addrs
6363
}
6464

65-
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) {
65+
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
66+
[]net.Addr, error) {
67+
6668
if m.failQuery {
67-
return nil, fmt.Errorf("fail")
69+
return false, nil, fmt.Errorf("fail")
6870
}
6971

7072
var nodeKey [33]byte
7173
copy(nodeKey[:], nodePub.SerializeCompressed())
7274

7375
addrs, ok := m.addrs[nodeKey]
74-
if !ok {
75-
return nil, fmt.Errorf("can't find addr")
76-
}
7776

78-
return addrs, nil
77+
return ok, addrs, nil
7978
}
8079

8180
// TestFetchBackupForChan tests that we're able to construct a single channel

channel_notifier.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{
4545
// chanUpdates channel to inform subscribers about new pending or
4646
// confirmed channels.
4747
sendChanOpenUpdate := func(newOrPendingChan *channeldb.OpenChannel) {
48-
nodeAddrs, err := c.addrs.AddrsForNode(
48+
_, nodeAddrs, err := c.addrs.AddrsForNode(
4949
newOrPendingChan.IdentityPub,
5050
)
5151
if err != nil {

channeldb/addr_source.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package channeldb
22

33
import (
4+
"errors"
45
"net"
56

67
"github.com/btcsuite/btcd/btcec/v2"
@@ -10,8 +11,9 @@ import (
1011
// node. It may combine the results of multiple address sources.
1112
type AddrSource interface {
1213
// AddrsForNode returns all known addresses for the target node public
13-
// key.
14-
AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
14+
// key. The returned boolean must indicate if the given node is unknown
15+
// to the backing source.
16+
AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error)
1517
}
1618

1719
// multiAddrSource is an implementation of AddrSource which gathers all the
@@ -31,22 +33,35 @@ func NewMultiAddrSource(sources ...AddrSource) AddrSource {
3133
}
3234

3335
// AddrsForNode returns all known addresses for the target node public key. It
34-
// queries all the address sources provided and de-duplicates the results.
36+
// queries all the address sources provided and de-duplicates the results. The
37+
// returned boolean is false only if none of the backing sources know of the
38+
// node.
3539
//
3640
// NOTE: this implements the AddrSource interface.
37-
func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr,
38-
error) {
41+
func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
42+
[]net.Addr, error) {
43+
44+
if len(c.sources) == 0 {
45+
return false, nil, errors.New("no address sources")
46+
}
3947

4048
// The multiple address sources will likely contain duplicate addresses,
4149
// so we use a map here to de-dup them.
4250
dedupedAddrs := make(map[string]net.Addr)
4351

52+
// known will be set to true if any backing source is aware of the node.
53+
var known bool
54+
4455
// Iterate over all the address sources and query each one for the
4556
// addresses it has for the node in question.
4657
for _, src := range c.sources {
47-
addrs, err := src.AddrsForNode(nodePub)
58+
isKnown, addrs, err := src.AddrsForNode(nodePub)
4859
if err != nil {
49-
return nil, err
60+
return false, nil, err
61+
}
62+
63+
if isKnown {
64+
known = true
5065
}
5166

5267
for _, addr := range addrs {
@@ -60,7 +75,7 @@ func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr,
6075
addrs = append(addrs, addr)
6176
}
6277

63-
return addrs, nil
78+
return known, addrs, nil
6479
}
6580

6681
// A compile-time check to ensure that multiAddrSource implements the AddrSource

channeldb/addr_source_test.go

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,12 @@ func TestMultiAddrSource(t *testing.T) {
3636

3737
// Let source 1 know of 2 addresses (addr 1 and 2) for node 1.
3838
src1.On("AddrsForNode", pk1).Return(
39-
[]net.Addr{addr1, addr2}, nil,
39+
true, []net.Addr{addr1, addr2}, nil,
4040
).Once()
4141

4242
// Let source 2 know of 2 addresses (addr 2 and 3) for node 1.
4343
src2.On("AddrsForNode", pk1).Return(
44+
true, []net.Addr{addr2, addr3}, nil,
4445
[]net.Addr{addr2, addr3}, nil,
4546
).Once()
4647

@@ -50,8 +51,9 @@ func TestMultiAddrSource(t *testing.T) {
5051

5152
// Query it for the addresses known for node 1. The results
5253
// should contain addr 1, 2 and 3.
53-
addrs, err := multiSrc.AddrsForNode(pk1)
54+
known, addrs, err := multiSrc.AddrsForNode(pk1)
5455
require.NoError(t, err)
56+
require.True(t, known)
5557
require.ElementsMatch(t, addrs, []net.Addr{addr1, addr2, addr3})
5658
})
5759

@@ -69,21 +71,49 @@ func TestMultiAddrSource(t *testing.T) {
6971

7072
// Let source 1 know of address 1 for node 1.
7173
src1.On("AddrsForNode", pk1).Return(
72-
[]net.Addr{addr1}, nil,
74+
true, []net.Addr{addr1}, nil,
7375
).Once()
74-
src2.On("AddrsForNode", pk1).Return(nil, nil).Once()
76+
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
7577

7678
// Create a multi-addr source that consists of both source 1
7779
// and 2.
7880
multiSrc := NewMultiAddrSource(src1, src2)
7981

8082
// Query it for the addresses known for node 1. The results
8183
// should contain addr 1.
82-
addrs, err := multiSrc.AddrsForNode(pk1)
84+
known, addrs, err := multiSrc.AddrsForNode(pk1)
8385
require.NoError(t, err)
86+
require.True(t, known)
8487
require.ElementsMatch(t, addrs, []net.Addr{addr1})
8588
})
8689

90+
t.Run("unknown address", func(t *testing.T) {
91+
t.Parallel()
92+
93+
var (
94+
src1 = newMockAddrSource(t)
95+
src2 = newMockAddrSource(t)
96+
)
97+
t.Cleanup(func() {
98+
src1.AssertExpectations(t)
99+
src2.AssertExpectations(t)
100+
})
101+
102+
// Create a multi-addr source that consists of both source 1
103+
// and 2. Neither source known of node 1.
104+
multiSrc := NewMultiAddrSource(src1, src2)
105+
106+
src1.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
107+
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
108+
109+
// Query it for the addresses known for node 1. It should return
110+
// false to indicate that the node is unknown to all backing
111+
// sources.
112+
known, addrs, err := multiSrc.AddrsForNode(pk1)
113+
require.NoError(t, err)
114+
require.False(t, known)
115+
require.Empty(t, addrs)
116+
})
87117
}
88118

89119
type mockAddrSource struct {
@@ -97,18 +127,18 @@ func newMockAddrSource(t *testing.T) *mockAddrSource {
97127
return &mockAddrSource{t: t}
98128
}
99129

100-
func (m *mockAddrSource) AddrsForNode(pub *btcec.PublicKey) ([]net.Addr,
130+
func (m *mockAddrSource) AddrsForNode(pub *btcec.PublicKey) (bool, []net.Addr,
101131
error) {
102132

103133
args := m.Called(pub)
104-
if args.Get(0) == nil {
105-
return nil, args.Error(1)
134+
if args.Get(1) == nil {
135+
return args.Bool(0), nil, args.Error(2)
106136
}
107137

108-
addrs, ok := args.Get(0).([]net.Addr)
138+
addrs, ok := args.Get(1).([]net.Addr)
109139
require.True(m.t, ok)
110140

111-
return addrs, args.Error(1)
141+
return args.Bool(0), addrs, args.Error(2)
112142
}
113143

114144
func newTestPubKey(t *testing.T) *btcec.PublicKey {

channeldb/db.go

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,46 +1345,62 @@ func (c *ChannelStateDB) RestoreChannelShells(channelShells ...*ChannelShell) er
13451345

13461346
// AddrsForNode consults the graph and channel database for all addresses known
13471347
// to the passed node public key.
1348-
func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr,
1349-
error) {
1348+
func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error) {
1349+
var (
1350+
// addrs holds the collection of deduplicated addresses we know
1351+
// of for the node.
1352+
addrs = make(map[string]net.Addr)
1353+
1354+
// known keeps track of if any of the backing sources know of
1355+
// this node.
1356+
known bool
1357+
)
13501358

1359+
// First, query the channel DB for its known addresses.
13511360
linkNode, err := d.channelStateDB.linkNodeDB.FetchLinkNode(nodePub)
1352-
if err != nil {
1353-
return nil, err
1361+
switch {
1362+
// If we get back a ErrNodeNotFound error, then this just means that the
1363+
// channel DB does not know of the error, but we don't error out here
1364+
// because we still want to check the graph db.
1365+
case err != nil && !errors.Is(err, ErrNodeNotFound):
1366+
return false, nil, err
1367+
1368+
// A nil error means the node is known.
1369+
case err == nil:
1370+
known = true
1371+
for _, addr := range linkNode.Addresses {
1372+
addrs[addr.String()] = addr
1373+
}
13541374
}
13551375

13561376
// We'll also query the graph for this peer to see if they have any
13571377
// addresses that we don't currently have stored within the link node
13581378
// database.
13591379
pubKey, err := route.NewVertexFromBytes(nodePub.SerializeCompressed())
13601380
if err != nil {
1361-
return nil, err
1381+
return false, nil, err
13621382
}
13631383
graphNode, err := d.graph.FetchLightningNode(pubKey)
1364-
if err != nil && err != graphdb.ErrGraphNodeNotFound {
1365-
return nil, err
1366-
} else if err == graphdb.ErrGraphNodeNotFound {
1367-
// If the node isn't found, then that's OK, as we still have the
1368-
// link node data. But any other error needs to be returned.
1369-
graphNode = &graphdb.LightningNode{}
1384+
switch {
1385+
// We don't consider it an error if the graph is unaware of the node.
1386+
case err != nil && !errors.Is(err, graphdb.ErrGraphNodeNotFound):
1387+
return false, nil, err
1388+
1389+
// If we do find the node, we add its addresses to our deduplicated set.
1390+
case err == nil:
1391+
known = true
1392+
for _, addr := range graphNode.Addresses {
1393+
addrs[addr.String()] = addr
1394+
}
13701395
}
13711396

1372-
// Now that we have both sources of addrs for this node, we'll use a
1373-
// map to de-duplicate any addresses between the two sources, and
1374-
// produce a final list of the combined addrs.
1375-
addrs := make(map[string]net.Addr)
1376-
for _, addr := range linkNode.Addresses {
1377-
addrs[addr.String()] = addr
1378-
}
1379-
for _, addr := range graphNode.Addresses {
1380-
addrs[addr.String()] = addr
1381-
}
1397+
// Convert the deduplicated set into a list.
13821398
dedupedAddrs := make([]net.Addr, 0, len(addrs))
13831399
for _, addr := range addrs {
13841400
dedupedAddrs = append(dedupedAddrs, addr)
13851401
}
13861402

1387-
return dedupedAddrs, nil
1403+
return known, dedupedAddrs, nil
13881404
}
13891405

13901406
// AbandonChannel attempts to remove the target channel from the open channel

channeldb/db_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func TestAddrsForNode(t *testing.T) {
219219

220220
// Now that we've created a link node, as well as a vertex for the
221221
// node, we'll query for all its addresses.
222-
nodeAddrs, err := fullDB.AddrsForNode(nodePub)
222+
_, nodeAddrs, err := fullDB.AddrsForNode(nodePub)
223223
require.NoError(t, err, "unable to obtain node addrs")
224224

225225
expectedAddrs := make(map[string]struct{})

0 commit comments

Comments
 (0)