autopilot: implement cached ChannelGraph

Using the cached implementation of a ChannelGraph greatly speeds up the
conversion of the channel database to a SimpleGraph.
This commit is contained in:
bitromortac 2021-12-04 12:28:07 +01:00
parent 52d56a8990
commit 45a2dc80c8
No known key found for this signature in database
GPG Key ID: 1965063FC13BEBE2
2 changed files with 91 additions and 1 deletions

View File

@ -455,6 +455,96 @@ func (m *memChannelGraph) addRandNode() (*btcec.PublicKey, error) {
return newPub, nil
}
// databaseChannelGraphCached wraps a channeldb.ChannelGraph instance with the
// necessary API to properly implement the autopilot.ChannelGraph interface.
type databaseChannelGraphCached struct {
db *channeldb.ChannelGraph
}
// A compile time assertion to ensure databaseChannelGraphCached meets the
// autopilot.ChannelGraph interface.
var _ ChannelGraph = (*databaseChannelGraphCached)(nil)
// ChannelGraphFromCachedDatabase returns an instance of the
// autopilot.ChannelGraph backed by a live, open channeldb instance.
func ChannelGraphFromCachedDatabase(db *channeldb.ChannelGraph) ChannelGraph {
return &databaseChannelGraphCached{
db: db,
}
}
// dbNodeCached is a wrapper struct around a database transaction for a
// channeldb.LightningNode. The wrapper methods implement the autopilot.Node
// interface.
type dbNodeCached struct {
node route.Vertex
channels map[uint64]*channeldb.DirectedChannel
}
// A compile time assertion to ensure dbNodeCached meets the autopilot.Node
// interface.
var _ Node = (*dbNodeCached)(nil)
// PubKey is the identity public key of the node.
//
// NOTE: Part of the autopilot.Node interface.
func (nc dbNodeCached) PubKey() [33]byte {
return nc.node
}
// Addrs returns a slice of publicly reachable public TCP addresses that the
// peer is known to be listening on.
//
// NOTE: Part of the autopilot.Node interface.
func (nc dbNodeCached) Addrs() []net.Addr {
// TODO: Add addresses to be usable by autopilot.
return []net.Addr{}
}
// ForEachChannel is a higher-order function that will be used to iterate
// through all edges emanating from/to the target node. For each active
// channel, this function should be called with the populated ChannelEdge that
// describes the active channel.
//
// NOTE: Part of the autopilot.Node interface.
func (nc dbNodeCached) ForEachChannel(cb func(ChannelEdge) error) error {
for cid, channel := range nc.channels {
edge := ChannelEdge{
ChanID: lnwire.NewShortChanIDFromInt(cid),
Capacity: channel.Capacity,
Peer: dbNodeCached{
node: channel.OtherNode,
},
}
if err := cb(edge); err != nil {
return err
}
}
return nil
}
// ForEachNode is a higher-order function that should be called once for each
// connected node within the channel graph. If the passed callback returns an
// error, then execution should be terminated.
//
// NOTE: Part of the autopilot.ChannelGraph interface.
func (dc *databaseChannelGraphCached) ForEachNode(cb func(Node) error) error {
return dc.db.ForEachNodeCached(func(n route.Vertex,
channels map[uint64]*channeldb.DirectedChannel) error {
if len(channels) > 0 {
node := dbNodeCached{
node: n,
channels: channels,
}
return cb(node)
}
return nil
})
}
// memNode is a purely in-memory implementation of the autopilot.Node
// interface.
type memNode struct {

View File

@ -5905,7 +5905,7 @@ func (r *rpcServer) GetNetworkInfo(ctx context.Context,
}
// Graph diameter.
channelGraph := autopilot.ChannelGraphFromDatabase(graph)
channelGraph := autopilot.ChannelGraphFromCachedDatabase(graph)
simpleGraph, err := autopilot.NewSimpleGraph(channelGraph)
if err != nil {
return nil, err