mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-20 02:27:21 +01:00
Merge pull request #7085 from bottlepay/graph-tlv
rpcserver: expose graph tlv
This commit is contained in:
commit
e65f05360e
@ -46,6 +46,10 @@
|
||||
skipped by specifying `skip_peer_alias_lookup`. `lncli fwdinghistory` also
|
||||
adds a flag `skip_peer_alias_lookup` to skip the lookup.
|
||||
|
||||
* The graph lookups method `DescribeGraph`, `GetNodeInfo` and `GetChanInfo` now
|
||||
[expose tlv data](https://github.com/lightningnetwork/lnd/pull/7085) that is
|
||||
broadcast over the gossip network.
|
||||
|
||||
## Wallet
|
||||
|
||||
* [Allows Taproot public keys and tap scripts to be imported as watch-only
|
||||
|
@ -84,6 +84,14 @@
|
||||
},
|
||||
"node2_policy": {
|
||||
"$ref": "#/definitions/lnrpcRoutingPolicy"
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom channel announcement tlv records."
|
||||
}
|
||||
},
|
||||
"description": "A fully authenticated channel along with all its unique attributes.\nOnce an authenticated channel announcement has been processed on the network,\nthen an instance of ChannelEdgeInfo encapsulating the channels attributes is\nstored. The other portions relevant to routing policy of a channel are stored\nwithin a ChannelEdgePolicy for each direction of the channel."
|
||||
@ -149,6 +157,14 @@
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/lnrpcFeature"
|
||||
}
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom node announcement tlv records."
|
||||
}
|
||||
},
|
||||
"description": "An individual vertex/node within the channel graph. A node is\nconnected to other nodes by one or more channel edges emanating from it. As the\ngraph is directed, a node will also have an incoming edge attached to it for\neach outgoing edge."
|
||||
@ -193,6 +209,14 @@
|
||||
"last_update": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom channel update tlv records."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3054,6 +3054,9 @@ message LightningNode {
|
||||
repeated NodeAddress addresses = 4;
|
||||
string color = 5;
|
||||
map<uint32, Feature> features = 6;
|
||||
|
||||
// Custom node announcement tlv records.
|
||||
map<uint64, bytes> custom_records = 7;
|
||||
}
|
||||
|
||||
message NodeAddress {
|
||||
@ -3069,6 +3072,9 @@ message RoutingPolicy {
|
||||
bool disabled = 5;
|
||||
uint64 max_htlc_msat = 6;
|
||||
uint32 last_update = 7;
|
||||
|
||||
// Custom channel update tlv records.
|
||||
map<uint64, bytes> custom_records = 8;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3096,6 +3102,9 @@ message ChannelEdge {
|
||||
|
||||
RoutingPolicy node1_policy = 7;
|
||||
RoutingPolicy node2_policy = 8;
|
||||
|
||||
// Custom channel announcement tlv records.
|
||||
map<uint64, bytes> custom_records = 9;
|
||||
}
|
||||
|
||||
message ChannelGraphRequest {
|
||||
|
@ -3845,6 +3845,14 @@
|
||||
},
|
||||
"node2_policy": {
|
||||
"$ref": "#/definitions/lnrpcRoutingPolicy"
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom channel announcement tlv records."
|
||||
}
|
||||
},
|
||||
"description": "A fully authenticated channel along with all its unique attributes.\nOnce an authenticated channel announcement has been processed on the network,\nthen an instance of ChannelEdgeInfo encapsulating the channels attributes is\nstored. The other portions relevant to routing policy of a channel are stored\nwithin a ChannelEdgePolicy for each direction of the channel."
|
||||
@ -5210,6 +5218,14 @@
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/lnrpcFeature"
|
||||
}
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom node announcement tlv records."
|
||||
}
|
||||
},
|
||||
"description": "An individual vertex/node within the channel graph. A node is\nconnected to other nodes by one or more channel edges emanating from it. As the\ngraph is directed, a node will also have an incoming edge attached to it for\neach outgoing edge."
|
||||
@ -6443,6 +6459,14 @@
|
||||
"last_update": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"custom_records": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
"description": "Custom channel update tlv records."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
138
rpcserver.go
138
rpcserver.go
@ -71,6 +71,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/rpcperms"
|
||||
"github.com/lightningnetwork/lnd/signal"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/lightningnetwork/lnd/watchtower"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
"github.com/tv42/zbase32"
|
||||
@ -5673,23 +5674,7 @@ func (r *rpcServer) DescribeGraph(ctx context.Context,
|
||||
// within the graph), collating their current state into the RPC
|
||||
// response.
|
||||
err := graph.ForEachNode(func(_ kvdb.RTx, node *channeldb.LightningNode) error {
|
||||
nodeAddrs := make([]*lnrpc.NodeAddress, 0)
|
||||
for _, addr := range node.Addresses {
|
||||
nodeAddr := &lnrpc.NodeAddress{
|
||||
Network: addr.Network(),
|
||||
Addr: addr.String(),
|
||||
}
|
||||
nodeAddrs = append(nodeAddrs, nodeAddr)
|
||||
}
|
||||
|
||||
lnNode := &lnrpc.LightningNode{
|
||||
LastUpdate: uint32(node.LastUpdate.Unix()),
|
||||
PubKey: hex.EncodeToString(node.PubKeyBytes[:]),
|
||||
Addresses: nodeAddrs,
|
||||
Alias: node.Alias,
|
||||
Color: routing.EncodeHexColor(node.Color),
|
||||
Features: invoicesrpc.CreateRPCFeatures(node.Features),
|
||||
}
|
||||
lnNode := marshalNode(node)
|
||||
|
||||
resp.Nodes = append(resp.Nodes, lnNode)
|
||||
|
||||
@ -5732,6 +5717,30 @@ func (r *rpcServer) DescribeGraph(ctx context.Context,
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// marshalExtraOpaqueData marshals the given tlv data. If the tlv stream is
|
||||
// malformed or empty, an empty map is returned. This makes the method safe to
|
||||
// use on unvalidated data.
|
||||
func marshalExtraOpaqueData(data []byte) map[uint64][]byte {
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
tlvStream, err := tlv.NewStream()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
parsedTypes, err := tlvStream.DecodeWithParsedTypes(r)
|
||||
if err != nil || len(parsedTypes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
records := make(map[uint64][]byte)
|
||||
for k, v := range parsedTypes {
|
||||
records[uint64(k)] = v
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
||||
|
||||
func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo,
|
||||
c1, c2 *channeldb.ChannelEdgePolicy) *lnrpc.ChannelEdge {
|
||||
|
||||
@ -5751,43 +5760,49 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo,
|
||||
lastUpdate = c2.LastUpdate.Unix()
|
||||
}
|
||||
|
||||
customRecords := marshalExtraOpaqueData(edgeInfo.ExtraOpaqueData)
|
||||
|
||||
edge := &lnrpc.ChannelEdge{
|
||||
ChannelId: edgeInfo.ChannelID,
|
||||
ChanPoint: edgeInfo.ChannelPoint.String(),
|
||||
// TODO(roasbeef): update should be on edge info itself
|
||||
LastUpdate: uint32(lastUpdate),
|
||||
Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1Bytes[:]),
|
||||
Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2Bytes[:]),
|
||||
Capacity: int64(edgeInfo.Capacity),
|
||||
LastUpdate: uint32(lastUpdate),
|
||||
Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1Bytes[:]),
|
||||
Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2Bytes[:]),
|
||||
Capacity: int64(edgeInfo.Capacity),
|
||||
CustomRecords: customRecords,
|
||||
}
|
||||
|
||||
if c1 != nil {
|
||||
edge.Node1Policy = &lnrpc.RoutingPolicy{
|
||||
TimeLockDelta: uint32(c1.TimeLockDelta),
|
||||
MinHtlc: int64(c1.MinHTLC),
|
||||
MaxHtlcMsat: uint64(c1.MaxHTLC),
|
||||
FeeBaseMsat: int64(c1.FeeBaseMSat),
|
||||
FeeRateMilliMsat: int64(c1.FeeProportionalMillionths),
|
||||
Disabled: c1.ChannelFlags&lnwire.ChanUpdateDisabled != 0,
|
||||
LastUpdate: uint32(c1.LastUpdate.Unix()),
|
||||
}
|
||||
edge.Node1Policy = marshalDBRoutingPolicy(c1)
|
||||
}
|
||||
|
||||
if c2 != nil {
|
||||
edge.Node2Policy = &lnrpc.RoutingPolicy{
|
||||
TimeLockDelta: uint32(c2.TimeLockDelta),
|
||||
MinHtlc: int64(c2.MinHTLC),
|
||||
MaxHtlcMsat: uint64(c2.MaxHTLC),
|
||||
FeeBaseMsat: int64(c2.FeeBaseMSat),
|
||||
FeeRateMilliMsat: int64(c2.FeeProportionalMillionths),
|
||||
Disabled: c2.ChannelFlags&lnwire.ChanUpdateDisabled != 0,
|
||||
LastUpdate: uint32(c2.LastUpdate.Unix()),
|
||||
}
|
||||
edge.Node2Policy = marshalDBRoutingPolicy(c2)
|
||||
}
|
||||
|
||||
return edge
|
||||
}
|
||||
|
||||
func marshalDBRoutingPolicy(
|
||||
policy *channeldb.ChannelEdgePolicy) *lnrpc.RoutingPolicy {
|
||||
|
||||
disabled := policy.ChannelFlags&lnwire.ChanUpdateDisabled != 0
|
||||
|
||||
customRecords := marshalExtraOpaqueData(policy.ExtraOpaqueData)
|
||||
|
||||
return &lnrpc.RoutingPolicy{
|
||||
TimeLockDelta: uint32(policy.TimeLockDelta),
|
||||
MinHtlc: int64(policy.MinHTLC),
|
||||
MaxHtlcMsat: uint64(policy.MaxHTLC),
|
||||
FeeBaseMsat: int64(policy.FeeBaseMSat),
|
||||
FeeRateMilliMsat: int64(policy.FeeProportionalMillionths),
|
||||
Disabled: disabled,
|
||||
LastUpdate: uint32(policy.LastUpdate.Unix()),
|
||||
CustomRecords: customRecords,
|
||||
}
|
||||
}
|
||||
|
||||
// GetNodeMetrics returns all available node metrics calculated from the
|
||||
// current channel graph.
|
||||
func (r *rpcServer) GetNodeMetrics(ctx context.Context,
|
||||
@ -5927,32 +5942,39 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeAddrs := make([]*lnrpc.NodeAddress, 0)
|
||||
for _, addr := range node.Addresses {
|
||||
nodeAddr := &lnrpc.NodeAddress{
|
||||
Network: addr.Network(),
|
||||
Addr: addr.String(),
|
||||
}
|
||||
nodeAddrs = append(nodeAddrs, nodeAddr)
|
||||
}
|
||||
|
||||
features := invoicesrpc.CreateRPCFeatures(node.Features)
|
||||
|
||||
return &lnrpc.NodeInfo{
|
||||
Node: &lnrpc.LightningNode{
|
||||
LastUpdate: uint32(node.LastUpdate.Unix()),
|
||||
PubKey: in.PubKey,
|
||||
Addresses: nodeAddrs,
|
||||
Alias: node.Alias,
|
||||
Color: routing.EncodeHexColor(node.Color),
|
||||
Features: features,
|
||||
},
|
||||
Node: marshalNode(node),
|
||||
NumChannels: numChannels,
|
||||
TotalCapacity: int64(totalCapacity),
|
||||
Channels: channels,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func marshalNode(node *channeldb.LightningNode) *lnrpc.LightningNode {
|
||||
nodeAddrs := make([]*lnrpc.NodeAddress, len(node.Addresses))
|
||||
for i, addr := range node.Addresses {
|
||||
nodeAddr := &lnrpc.NodeAddress{
|
||||
Network: addr.Network(),
|
||||
Addr: addr.String(),
|
||||
}
|
||||
nodeAddrs[i] = nodeAddr
|
||||
}
|
||||
|
||||
features := invoicesrpc.CreateRPCFeatures(node.Features)
|
||||
|
||||
customRecords := marshalExtraOpaqueData(node.ExtraOpaqueData)
|
||||
|
||||
return &lnrpc.LightningNode{
|
||||
LastUpdate: uint32(node.LastUpdate.Unix()),
|
||||
PubKey: hex.EncodeToString(node.PubKeyBytes[:]),
|
||||
Addresses: nodeAddrs,
|
||||
Alias: node.Alias,
|
||||
Color: routing.EncodeHexColor(node.Color),
|
||||
Features: features,
|
||||
CustomRecords: customRecords,
|
||||
}
|
||||
}
|
||||
|
||||
// QueryRoutes attempts to query the daemons' Channel Router for a possible
|
||||
// route to a target destination capable of carrying a specific amount of
|
||||
// satoshis within the route's flow. The returned route contains the full
|
||||
|
Loading…
Reference in New Issue
Block a user