Merge pull request #7085 from bottlepay/graph-tlv

rpcserver: expose graph tlv
This commit is contained in:
Oliver Gugger 2022-10-26 13:17:35 +02:00 committed by GitHub
commit e65f05360e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1785 additions and 1642 deletions

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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."
}
}
},

View File

@ -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