package main import ( "fmt" "hash/crc32" "strconv" "github.com/ipfs/go-cid" "gopkg.in/urfave/cli.v2" ) var dotCmd = &cli.Command{ Name: "dot", Usage: "generate dot graphs", ArgsUsage: " ", Action: func(cctx *cli.Context) error { st, err := openStorage(cctx.String("db")) if err != nil { return err } minH, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32) tosee, err := strconv.ParseInt(cctx.Args().Get(1), 10, 32) maxH := minH + tosee res, err := st.db.Query(`select block, parent, b.miner, b.height, p.height from block_parents inner join blocks b on block_parents.block = b.cid inner join blocks p on block_parents.parent = p.cid where b.height > ? and b.height < ?`, minH, maxH) if err != nil { return err } fmt.Println("digraph D {") for res.Next() { var block, parent, miner string var height, ph uint64 if err := res.Scan(&block, &parent, &miner, &height, &ph); err != nil { return err } bc, err := cid.Parse(block) if err != nil { return err } has := st.hasBlock(bc) col := crc32.Checksum([]byte(miner), crc32.MakeTable(crc32.Castagnoli))&0xc0c0c0c0 + 0x30303030 hasstr := "" if !has { //col = 0xffffffff hasstr = " UNSYNCED" } nulls := height - ph - 1 for i := uint64(0); i < nulls; i++ { name := block + "NP" + fmt.Sprint(i) fmt.Printf("%s [label = \"NULL:%d\", fillcolor = \"#ffddff\", style=filled, forcelabels=true]\n%s -> %s\n", name, height-nulls+i, name, parent) parent = name } fmt.Printf("%s [label = \"%s:%d%s\", fillcolor = \"#%06x\", style=filled, forcelabels=true]\n%s -> %s\n", block, miner, height, hasstr, col, block, parent) } if res.Err() != nil { return res.Err() } fmt.Println("}") return nil }, }