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"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -491,3 +492,95 @@ func RootFromProof(proof *Proof, k, v *big.Int) (*Hash, error) {
|
|||||||
}
|
}
|
||||||
return midKey, nil
|
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