mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-19 18:48:03 +01: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:
@@ -35,3 +35,13 @@ type NetworkStats struct {
|
|||||||
// NumZombies is the number of zombie channels in the graph.
|
// NumZombies is the number of zombie channels in the graph.
|
||||||
NumZombies uint64
|
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"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
@@ -360,6 +361,47 @@ func (s *DBSource) NetworkStats(_ context.Context) (*models.NetworkStats,
|
|||||||
}, nil
|
}, 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
|
// kvdbRTx is an implementation of graphdb.RTx backed by a KVDB database read
|
||||||
// transaction.
|
// transaction.
|
||||||
type kvdbRTx struct {
|
type kvdbRTx struct {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
|
"github.com/lightningnetwork/lnd/autopilot"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/discovery"
|
"github.com/lightningnetwork/lnd/discovery"
|
||||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||||
@@ -16,6 +17,8 @@ import (
|
|||||||
|
|
||||||
// GraphSource defines the read-only graph interface required by LND for graph
|
// GraphSource defines the read-only graph interface required by LND for graph
|
||||||
// related queries.
|
// related queries.
|
||||||
|
//
|
||||||
|
//nolint:interfacebloat
|
||||||
type GraphSource interface {
|
type GraphSource interface {
|
||||||
session.ReadOnlyGraph
|
session.ReadOnlyGraph
|
||||||
invoicesrpc.GraphSource
|
invoicesrpc.GraphSource
|
||||||
@@ -78,4 +81,9 @@ type GraphSource interface {
|
|||||||
// NetworkStats returns statistics concerning the current state of the
|
// NetworkStats returns statistics concerning the current state of the
|
||||||
// known channel graph within the network.
|
// known channel graph within the network.
|
||||||
NetworkStats(ctx context.Context) (*models.NetworkStats, error)
|
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"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -6701,43 +6700,27 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &lnrpc.NodeMetricsResponse{
|
graph := r.server.graphSource
|
||||||
BetweennessCentrality: make(map[string]*lnrpc.FloatMetric),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain the pointer to the global singleton channel graph, this will
|
// Calculate betweenness centrality if requested. Note that depending on
|
||||||
// provide a consistent view of the graph due to bolt db's
|
// the graph size, this may take up to a few minutes.
|
||||||
// transactional model.
|
centrality, err := graph.BetweennessCentrality(ctx)
|
||||||
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(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
return &lnrpc.NodeMetricsResponse{
|
||||||
centrality := centralityMetric.GetMetric(true)
|
BetweennessCentrality: result,
|
||||||
for nodeID, val := range centrality {
|
}, nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetChanInfo returns the latest authenticated network announcement for the
|
// GetChanInfo returns the latest authenticated network announcement for the
|
||||||
|
|||||||
Reference in New Issue
Block a user