mirror of
https://github.com/arnaucube/go-merkletree-iden3.git
synced 2026-02-07 03:26:46 +01:00
Add Graphviz methods
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
@@ -491,3 +492,95 @@ func RootFromProof(proof *Proof, k, v *big.Int) (*Hash, error) {
|
||||
}
|
||||
return midKey, nil
|
||||
}
|
||||
|
||||
// walk is a helper recursive function to iterate over all tree branches
|
||||
func (mt *MerkleTree) walk(key *Hash, f func(*Node)) error {
|
||||
n, err := mt.GetNode(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch n.Type {
|
||||
case NodeTypeEmpty:
|
||||
f(n)
|
||||
case NodeTypeLeaf:
|
||||
f(n)
|
||||
case NodeTypeMiddle:
|
||||
f(n)
|
||||
if err := mt.walk(n.ChildL, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mt.walk(n.ChildR, f); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return ErrInvalidNodeFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Walk iterates over all the branches of a MerkleTree with the given rootKey
|
||||
// if rootKey is nil, it will get the current RootKey of the current state of the MerkleTree.
|
||||
// For each node, it calls the f function given in the parameters.
|
||||
// See some examples of the Walk function usage in the merkletree_test.go
|
||||
// test functions: TestMTWalk, TestMTWalkGraphViz, TestMTWalkDumpClaims
|
||||
func (mt *MerkleTree) Walk(rootKey *Hash, f func(*Node)) error {
|
||||
if rootKey == nil {
|
||||
rootKey = mt.Root()
|
||||
}
|
||||
err := mt.walk(rootKey, f)
|
||||
return err
|
||||
}
|
||||
|
||||
// GraphViz uses Walk function to generate a string GraphViz representation of the
|
||||
// tree and writes it to w
|
||||
func (mt *MerkleTree) GraphViz(w io.Writer, rootKey *Hash) error {
|
||||
fmt.Fprintf(w, `digraph hierarchy {
|
||||
node [fontname=Monospace,fontsize=10,shape=box]
|
||||
`)
|
||||
cnt := 0
|
||||
var errIn error
|
||||
err := mt.Walk(rootKey, func(n *Node) {
|
||||
k, err := n.Key()
|
||||
if err != nil {
|
||||
errIn = err
|
||||
}
|
||||
switch n.Type {
|
||||
case NodeTypeEmpty:
|
||||
case NodeTypeLeaf:
|
||||
fmt.Fprintf(w, "\"%v\" [style=filled];\n", k.BigInt().String())
|
||||
case NodeTypeMiddle:
|
||||
lr := [2]string{n.ChildL.BigInt().String(), n.ChildR.BigInt().String()}
|
||||
for i := range lr {
|
||||
if lr[i] == "0" {
|
||||
lr[i] = fmt.Sprintf("empty%v", cnt)
|
||||
fmt.Fprintf(w, "\"%v\" [style=dashed,label=0];\n", lr[i])
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "\"%v\" -> {\"%v\" \"%v\"}\n", k.BigInt().String(), lr[0], lr[1])
|
||||
default:
|
||||
}
|
||||
})
|
||||
fmt.Fprintf(w, "}\n")
|
||||
if errIn != nil {
|
||||
return errIn
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// PrintGraphViz prints directly the GraphViz() output
|
||||
func (mt *MerkleTree) PrintGraphViz(rootKey *Hash) error {
|
||||
if rootKey == nil {
|
||||
rootKey = mt.Root()
|
||||
}
|
||||
w := bytes.NewBufferString("")
|
||||
fmt.Fprintf(w, "--------\nGraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n")
|
||||
err := mt.GraphViz(w, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "End of GraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n--------\n")
|
||||
|
||||
fmt.Println(w)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user