mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-04-21 22:15:38 +02:00
graph+lnd: add BetweennessCentrality to GraphSource interface
So that the calcuation is abstracted behind the interface and not necessarily dependent on LND's local channel graph.
This commit is contained in:
parent
80070618a7
commit
f36fbd0e45
@ -35,3 +35,13 @@ type NetworkStats struct {
|
||||
// NumZombies is the number of zombie channels in the graph.
|
||||
NumZombies uint64
|
||||
}
|
||||
|
||||
// BetweennessCentrality represents the betweenness centrality of a node in the
|
||||
// graph.
|
||||
type BetweennessCentrality struct {
|
||||
// Normalized is the normalized betweenness centrality of a node.
|
||||
Normalized float64
|
||||
|
||||
// NonNormalized is the non-normalized betweenness centrality of a node.
|
||||
NonNormalized float64
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
@ -360,6 +361,47 @@ func (s *DBSource) NetworkStats(_ context.Context) (*models.NetworkStats,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BetweennessCentrality computes the normalised and non-normalised betweenness
|
||||
// centrality for each node in the graph.
|
||||
//
|
||||
// NOTE: this is part of the GraphSource interface.
|
||||
func (s *DBSource) BetweennessCentrality(_ context.Context) (
|
||||
map[autopilot.NodeID]*models.BetweennessCentrality, error) {
|
||||
|
||||
channelGraph := autopilot.ChannelGraphFromDatabase(s.db)
|
||||
centralityMetric, err := autopilot.NewBetweennessCentralityMetric(
|
||||
runtime.NumCPU(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := centralityMetric.Refresh(channelGraph); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
centrality := make(map[autopilot.NodeID]*models.BetweennessCentrality)
|
||||
|
||||
for nodeID, val := range centralityMetric.GetMetric(true) {
|
||||
centrality[nodeID] = &models.BetweennessCentrality{
|
||||
Normalized: val,
|
||||
}
|
||||
}
|
||||
|
||||
for nodeID, val := range centralityMetric.GetMetric(false) {
|
||||
if _, ok := centrality[nodeID]; !ok {
|
||||
centrality[nodeID] = &models.BetweennessCentrality{
|
||||
Normalized: val,
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
centrality[nodeID].NonNormalized = val
|
||||
}
|
||||
|
||||
return centrality, nil
|
||||
}
|
||||
|
||||
// kvdbRTx is an implementation of graphdb.RTx backed by a KVDB database read
|
||||
// transaction.
|
||||
type kvdbRTx struct {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/lightningnetwork/lnd/autopilot"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/discovery"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
@ -16,6 +17,8 @@ import (
|
||||
|
||||
// GraphSource defines the read-only graph interface required by LND for graph
|
||||
// related queries.
|
||||
//
|
||||
//nolint:interfacebloat
|
||||
type GraphSource interface {
|
||||
session.ReadOnlyGraph
|
||||
invoicesrpc.GraphSource
|
||||
@ -78,4 +81,9 @@ type GraphSource interface {
|
||||
// NetworkStats returns statistics concerning the current state of the
|
||||
// known channel graph within the network.
|
||||
NetworkStats(ctx context.Context) (*models.NetworkStats, error)
|
||||
|
||||
// BetweennessCentrality computes the normalised and non-normalised
|
||||
// betweenness centrality for each node in the graph.
|
||||
BetweennessCentrality(ctx context.Context) (
|
||||
map[autopilot.NodeID]*models.BetweennessCentrality, error)
|
||||
}
|
||||
|
47
rpcserver.go
47
rpcserver.go
@ -12,7 +12,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -6701,43 +6700,27 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context,
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
resp := &lnrpc.NodeMetricsResponse{
|
||||
BetweennessCentrality: make(map[string]*lnrpc.FloatMetric),
|
||||
}
|
||||
graph := r.server.graphSource
|
||||
|
||||
// Obtain the pointer to the global singleton channel graph, this will
|
||||
// provide a consistent view of the graph due to bolt db's
|
||||
// transactional model.
|
||||
graph := r.server.graphDB
|
||||
|
||||
// Calculate betweenness centrality if requested. Note that depending on the
|
||||
// graph size, this may take up to a few minutes.
|
||||
channelGraph := autopilot.ChannelGraphFromDatabase(graph)
|
||||
centralityMetric, err := autopilot.NewBetweennessCentralityMetric(
|
||||
runtime.NumCPU(),
|
||||
)
|
||||
// Calculate betweenness centrality if requested. Note that depending on
|
||||
// the graph size, this may take up to a few minutes.
|
||||
centrality, err := graph.BetweennessCentrality(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := centralityMetric.Refresh(channelGraph); err != nil {
|
||||
return nil, err
|
||||
|
||||
result := make(map[string]*lnrpc.FloatMetric)
|
||||
for nodeID, betweenness := range centrality {
|
||||
id := hex.EncodeToString(nodeID[:])
|
||||
result[id] = &lnrpc.FloatMetric{
|
||||
Value: betweenness.NonNormalized,
|
||||
NormalizedValue: betweenness.Normalized,
|
||||
}
|
||||
}
|
||||
|
||||
// Fill normalized and non normalized centrality.
|
||||
centrality := centralityMetric.GetMetric(true)
|
||||
for nodeID, val := range centrality {
|
||||
resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])] =
|
||||
&lnrpc.FloatMetric{
|
||||
NormalizedValue: val,
|
||||
}
|
||||
}
|
||||
|
||||
centrality = centralityMetric.GetMetric(false)
|
||||
for nodeID, val := range centrality {
|
||||
resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])].Value = val
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return &lnrpc.NodeMetricsResponse{
|
||||
BetweennessCentrality: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetChanInfo returns the latest authenticated network announcement for the
|
||||
|
Loading…
x
Reference in New Issue
Block a user