lncli: remove --render option from describegraph

This commit is contained in:
Johan T. Halseth 2018-08-17 09:36:56 +02:00
parent 643618b4f6
commit c39c2d7c37
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -11,15 +11,12 @@ import (
"io/ioutil" "io/ioutil"
"math" "math"
"os" "os"
"os/exec"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"github.com/awalterschulze/gographviz"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil"
"github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
@ -2344,12 +2341,6 @@ var describeGraphCommand = cli.Command{
Description: "Prints a human readable version of the known channel " + Description: "Prints a human readable version of the known channel " +
"graph from the PoV of the node", "graph from the PoV of the node",
Usage: "Describe the network graph.", Usage: "Describe the network graph.",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "render",
Usage: "If set, then an image of graph will be generated and displayed. The generated image is stored within the current directory with a file name of 'graph.svg'",
},
},
Action: actionDecorator(describeGraph), Action: actionDecorator(describeGraph),
} }
@ -2364,12 +2355,6 @@ func describeGraph(ctx *cli.Context) error {
return err return err
} }
// If the draw flag is on, then we'll use the 'dot' command to create a
// visualization of the graph itself.
if ctx.Bool("render") {
return drawChannelGraph(graph)
}
printRespJSON(graph) printRespJSON(graph)
return nil return nil
} }
@ -2405,135 +2390,6 @@ func normalizeFunc(edges []*lnrpc.ChannelEdge, scaleFactor float64) func(int64)
} }
} }
func drawChannelGraph(graph *lnrpc.ChannelGraph) error {
// First we'll create a temporary file that we'll write the compiled
// string that describes our graph in the dot format to.
tempDotFile, err := ioutil.TempFile("", "")
if err != nil {
return err
}
defer os.Remove(tempDotFile.Name())
// Next, we'll create (or re-create) the file that the final graph
// image will be written to.
imageFile, err := os.Create("graph.svg")
if err != nil {
return err
}
// With our temporary files set up, we'll initialize the graphviz
// object that we'll use to draw our graph.
graphName := "LightningNetwork"
graphCanvas := gographviz.NewGraph()
graphCanvas.SetName(graphName)
graphCanvas.SetDir(false)
const numKeyChars = 10
truncateStr := func(k string, n uint) string {
return k[:n]
}
// For each node within the graph, we'll add a new vertex to the graph.
for _, node := range graph.Nodes {
// Rather than using the entire hex-encoded string, we'll only
// use the first 10 characters. We also add a prefix of "Z" as
// graphviz is unable to parse the compressed pubkey as a
// non-integer.
//
// TODO(roasbeef): should be able to get around this?
nodeID := fmt.Sprintf(`"%v"`, truncateStr(node.PubKey, numKeyChars))
attrs := gographviz.Attrs{}
if node.Color != "" {
attrs["color"] = fmt.Sprintf(`"%v"`, node.Color)
}
graphCanvas.AddNode(graphName, nodeID, attrs)
}
normalize := normalizeFunc(graph.Edges, 3)
// Similarly, for each edge we'll add an edge between the corresponding
// nodes added to the graph above.
for _, edge := range graph.Edges {
// Once again, we add a 'Z' prefix so we're compliant with the
// dot grammar.
src := fmt.Sprintf(`"%v"`, truncateStr(edge.Node1Pub, numKeyChars))
dest := fmt.Sprintf(`"%v"`, truncateStr(edge.Node2Pub, numKeyChars))
// The weight for our edge will be the total capacity of the
// channel, in BTC.
// TODO(roasbeef): can also factor in the edges time-lock delta
// and fee information
amt := btcutil.Amount(edge.Capacity).ToBTC()
edgeWeight := strconv.FormatFloat(amt, 'f', -1, 64)
// The label for each edge will simply be a truncated version
// of its channel ID.
chanIDStr := strconv.FormatUint(edge.ChannelId, 10)
edgeLabel := fmt.Sprintf(`"cid:%v"`, truncateStr(chanIDStr, 7))
// We'll also use a normalized version of the channels'
// capacity in satoshis in order to modulate the "thickness" of
// the line that creates the edge within the graph.
normalizedCapacity := normalize(edge.Capacity)
edgeThickness := strconv.FormatFloat(normalizedCapacity, 'f', -1, 64)
// If there's only a single channel in the graph, then we'll
// just set the edge thickness to 1 for everything.
if math.IsNaN(normalizedCapacity) {
edgeThickness = "1"
}
// TODO(roasbeef): color code based on percentile capacity
graphCanvas.AddEdge(src, dest, false, gographviz.Attrs{
"penwidth": edgeThickness,
"weight": edgeWeight,
"label": edgeLabel,
})
}
// With the declarative generation of the graph complete, we now write
// the dot-string description of the graph
graphDotString := graphCanvas.String()
if _, err := tempDotFile.WriteString(graphDotString); err != nil {
return err
}
if err := tempDotFile.Sync(); err != nil {
return err
}
var errBuffer bytes.Buffer
// Once our dot file has been written to disk, we can use the dot
// command itself to generate the drawn rendering of the graph
// described.
drawCmd := exec.Command("dot", "-T"+"svg", "-o"+imageFile.Name(),
tempDotFile.Name())
drawCmd.Stderr = &errBuffer
if err := drawCmd.Run(); err != nil {
fmt.Println("error rendering graph: ", errBuffer.String())
fmt.Println("dot: ", graphDotString)
return err
}
errBuffer.Reset()
// Finally, we'll open the drawn graph to display to the user.
openCmd := exec.Command("open", imageFile.Name())
openCmd.Stderr = &errBuffer
if err := openCmd.Run(); err != nil {
fmt.Println("error opening rendered graph image: ",
errBuffer.String())
return err
}
return nil
}
var listPaymentsCommand = cli.Command{ var listPaymentsCommand = cli.Command{
Name: "listpayments", Name: "listpayments",
Category: "Payments", Category: "Payments",