Skip to content

Commit 08e9703

Browse files
authored
chore(trie): improve String() methods for trie.Trie and node.Node (#2238)
1 parent c470a16 commit 08e9703

File tree

9 files changed

+239
-84
lines changed

9 files changed

+239
-84
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ require (
3737
github.com/nanobox-io/golang-scribble v0.0.0-20190309225732-aa3e7c118975
3838
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
3939
github.com/perlin-network/life v0.0.0-20191203030451-05c0e0f7eaea
40+
github.com/qdm12/gotree v0.2.0
4041
github.com/stretchr/testify v1.7.0
4142
github.com/urfave/cli v1.22.5
4243
github.com/wasmerio/go-ext-wasm v0.3.2-0.20200326095750-0a32be6068ec

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,8 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0
11561156
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
11571157
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
11581158
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
1159+
github.com/qdm12/gotree v0.2.0 h1:+58ltxkNLUyHtATFereAcOjBVfY6ETqRex8XK90Fb/c=
1160+
github.com/qdm12/gotree v0.2.0/go.mod h1:1SdFaqKZuI46U1apbXIf25pDMNnrPuYLEqMF/qL4lY4=
11591161
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
11601162
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
11611163
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=

internal/trie/node/branch.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
package node
55

66
import (
7-
"fmt"
87
"sync"
98

10-
"github.com/ChainSafe/gossamer/lib/common"
9+
"github.com/qdm12/gotree"
1110
)
1211

1312
var _ Node = (*Branch)(nil)
@@ -51,10 +50,26 @@ func (b *Branch) Type() Type {
5150
}
5251

5352
func (b *Branch) String() string {
54-
if len(b.Value) > 1024 {
55-
return fmt.Sprintf("branch key=0x%x childrenBitmap=%b value (hashed)=0x%x dirty=%t",
56-
b.Key, b.ChildrenBitmap(), common.MustBlake2bHash(b.Value), b.Dirty)
53+
return b.StringNode().String()
54+
}
55+
56+
// StringNode returns a gotree compatible node for String methods.
57+
func (b *Branch) StringNode() (stringNode *gotree.Node) {
58+
stringNode = gotree.New("Branch")
59+
stringNode.Appendf("Generation: %d", b.Generation)
60+
stringNode.Appendf("Dirty: %t", b.Dirty)
61+
stringNode.Appendf("Key: " + bytesToString(b.Key))
62+
stringNode.Appendf("Value: " + bytesToString(b.Value))
63+
stringNode.Appendf("Calculated encoding: " + bytesToString(b.Encoding))
64+
stringNode.Appendf("Calculated digest: " + bytesToString(b.hashDigest))
65+
66+
for i, child := range b.Children {
67+
if child == nil {
68+
continue
69+
}
70+
childNode := stringNode.Appendf("Child %d", i)
71+
childNode.AppendNode(child.StringNode())
5772
}
58-
return fmt.Sprintf("branch key=0x%x childrenBitmap=%b value=0x%x dirty=%t",
59-
b.Key, b.ChildrenBitmap(), b.Value, b.Dirty)
73+
74+
return stringNode
6075
}

internal/trie/node/branch_test.go

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,13 @@ func Test_Branch_String(t *testing.T) {
7777
}{
7878
"empty branch": {
7979
branch: &Branch{},
80-
s: "branch key=0x childrenBitmap=0 value=0x dirty=false",
80+
s: `Branch
81+
├── Generation: 0
82+
├── Dirty: false
83+
├── Key: nil
84+
├── Value: nil
85+
├── Calculated encoding: nil
86+
└── Calculated digest: nil`,
8187
},
8288
"branch with value smaller than 1024": {
8389
branch: &Branch{
@@ -94,7 +100,37 @@ func Test_Branch_String(t *testing.T) {
94100
nil, nil, nil, nil,
95101
},
96102
},
97-
s: "branch key=0x0102 childrenBitmap=100010001000 value=0x0304 dirty=true",
103+
s: `Branch
104+
├── Generation: 0
105+
├── Dirty: true
106+
├── Key: 0x0102
107+
├── Value: 0x0304
108+
├── Calculated encoding: nil
109+
├── Calculated digest: nil
110+
├── Child 3
111+
| └── Leaf
112+
| ├── Generation: 0
113+
| ├── Dirty: false
114+
| ├── Key: nil
115+
| ├── Value: nil
116+
| ├── Calculated encoding: nil
117+
| └── Calculated digest: nil
118+
├── Child 7
119+
| └── Branch
120+
| ├── Generation: 0
121+
| ├── Dirty: false
122+
| ├── Key: nil
123+
| ├── Value: nil
124+
| ├── Calculated encoding: nil
125+
| └── Calculated digest: nil
126+
└── Child 11
127+
└── Leaf
128+
├── Generation: 0
129+
├── Dirty: false
130+
├── Key: nil
131+
├── Value: nil
132+
├── Calculated encoding: nil
133+
└── Calculated digest: nil`,
98134
},
99135
"branch with value higher than 1024": {
100136
branch: &Branch{
@@ -111,9 +147,37 @@ func Test_Branch_String(t *testing.T) {
111147
nil, nil, nil, nil,
112148
},
113149
},
114-
s: "branch key=0x0102 childrenBitmap=100010001000 " +
115-
"value (hashed)=0x307861663233363133353361303538646238383034626337353735323831663131663735313265326331346336373032393864306232336630396538386266333066 " + //nolint:lll
116-
"dirty=true",
150+
s: `Branch
151+
├── Generation: 0
152+
├── Dirty: true
153+
├── Key: 0x0102
154+
├── Value: 0x0000000000000000...0000000000000000
155+
├── Calculated encoding: nil
156+
├── Calculated digest: nil
157+
├── Child 3
158+
| └── Leaf
159+
| ├── Generation: 0
160+
| ├── Dirty: false
161+
| ├── Key: nil
162+
| ├── Value: nil
163+
| ├── Calculated encoding: nil
164+
| └── Calculated digest: nil
165+
├── Child 7
166+
| └── Branch
167+
| ├── Generation: 0
168+
| ├── Dirty: false
169+
| ├── Key: nil
170+
| ├── Value: nil
171+
| ├── Calculated encoding: nil
172+
| └── Calculated digest: nil
173+
└── Child 11
174+
└── Leaf
175+
├── Generation: 0
176+
├── Dirty: false
177+
├── Key: nil
178+
├── Value: nil
179+
├── Calculated encoding: nil
180+
└── Calculated digest: nil`,
117181
},
118182
}
119183

internal/trie/node/leaf.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"fmt"
88
"sync"
99

10-
"github.com/ChainSafe/gossamer/lib/common"
10+
"github.com/qdm12/gotree"
1111
)
1212

1313
var _ Node = (*Leaf)(nil)
@@ -47,8 +47,29 @@ func (l *Leaf) Type() Type {
4747
}
4848

4949
func (l *Leaf) String() string {
50-
if len(l.Value) > 1024 {
51-
return fmt.Sprintf("leaf key=0x%x value (hashed)=0x%x dirty=%t", l.Key, common.MustBlake2bHash(l.Value), l.Dirty)
50+
return l.StringNode().String()
51+
}
52+
53+
// StringNode returns a gotree compatible node for String methods.
54+
func (l *Leaf) StringNode() (stringNode *gotree.Node) {
55+
stringNode = gotree.New("Leaf")
56+
stringNode.Appendf("Generation: %d", l.Generation)
57+
stringNode.Appendf("Dirty: %t", l.Dirty)
58+
stringNode.Appendf("Key: " + bytesToString(l.Key))
59+
stringNode.Appendf("Value: " + bytesToString(l.Value))
60+
stringNode.Appendf("Calculated encoding: " + bytesToString(l.Encoding))
61+
stringNode.Appendf("Calculated digest: " + bytesToString(l.hashDigest))
62+
return stringNode
63+
}
64+
65+
func bytesToString(b []byte) (s string) {
66+
switch {
67+
case b == nil:
68+
return "nil"
69+
case len(b) <= 20:
70+
return fmt.Sprintf("0x%x", b)
71+
default:
72+
return fmt.Sprintf("0x%x...%x", b[:8], b[len(b)-8:])
5273
}
53-
return fmt.Sprintf("leaf key=0x%x value=0x%x dirty=%t", l.Key, l.Value, l.Dirty)
74+
5475
}

internal/trie/node/leaf_test.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,41 @@ func Test_Leaf_String(t *testing.T) {
5252
}{
5353
"empty leaf": {
5454
leaf: &Leaf{},
55-
s: "leaf key=0x value=0x dirty=false",
55+
s: `Leaf
56+
├── Generation: 0
57+
├── Dirty: false
58+
├── Key: nil
59+
├── Value: nil
60+
├── Calculated encoding: nil
61+
└── Calculated digest: nil`,
5662
},
5763
"leaf with value smaller than 1024": {
5864
leaf: &Leaf{
5965
Key: []byte{1, 2},
6066
Value: []byte{3, 4},
6167
Dirty: true,
6268
},
63-
s: "leaf key=0x0102 value=0x0304 dirty=true",
69+
s: `Leaf
70+
├── Generation: 0
71+
├── Dirty: true
72+
├── Key: 0x0102
73+
├── Value: 0x0304
74+
├── Calculated encoding: nil
75+
└── Calculated digest: nil`,
6476
},
6577
"leaf with value higher than 1024": {
6678
leaf: &Leaf{
6779
Key: []byte{1, 2},
6880
Value: make([]byte, 1025),
6981
Dirty: true,
7082
},
71-
s: "leaf key=0x0102 " +
72-
"value (hashed)=0x307861663233363133353361303538646238383034626337353735323831663131663735313265326331346336373032393864306232336630396538386266333066 " + //nolint:lll
73-
"dirty=true",
83+
s: `Leaf
84+
├── Generation: 0
85+
├── Dirty: true
86+
├── Key: 0x0102
87+
├── Value: 0x0000000000000000...0000000000000000
88+
├── Calculated encoding: nil
89+
└── Calculated digest: nil`,
7490
},
7591
}
7692

internal/trie/node/node.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
package node
55

6+
import "github.com/qdm12/gotree"
7+
68
// Node is a node in the trie and can be a leaf or a branch.
79
type Node interface {
810
Encode(buffer Buffer) (err error) // TODO change to io.Writer
@@ -20,4 +22,5 @@ type Node interface {
2022
SetGeneration(generation uint64)
2123
Copy(copyChildren bool) Node
2224
Type() Type
25+
StringNode() (stringNode *gotree.Node)
2326
}

lib/trie/print.go

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,73 +3,11 @@
33

44
package trie
55

6-
import (
7-
"bytes"
8-
"fmt"
9-
10-
"github.com/ChainSafe/gossamer/internal/trie/node"
11-
"github.com/ChainSafe/gossamer/internal/trie/pools"
12-
"github.com/ChainSafe/gossamer/lib/common"
13-
14-
"github.com/disiqueira/gotree"
15-
)
16-
176
// String returns the trie stringified through pre-order traversal
187
func (t *Trie) String() string {
198
if t.root == nil {
209
return "empty"
2110
}
2211

23-
tree := gotree.New(fmt.Sprintf("Trie root=0x%x", t.root.GetHash()))
24-
t.string(tree, t.root, 0)
25-
return fmt.Sprintf("\n%s", tree.Print())
26-
}
27-
28-
func (t *Trie) string(tree gotree.Tree, curr Node, idx int) {
29-
switch c := curr.(type) {
30-
case *node.Branch:
31-
buffer := pools.EncodingBuffers.Get().(*bytes.Buffer)
32-
buffer.Reset()
33-
34-
_ = c.Encode(buffer)
35-
encoding := buffer.Bytes()
36-
37-
var bstr string
38-
if len(encoding) > 1024 {
39-
bstr = fmt.Sprintf("idx=%d %s hash=%x gen=%d",
40-
idx, c, common.MustBlake2bHash(encoding), c.GetGeneration())
41-
} else {
42-
bstr = fmt.Sprintf("idx=%d %s encode=%x gen=%d", idx, c.String(), encoding, c.GetGeneration())
43-
}
44-
45-
pools.EncodingBuffers.Put(buffer)
46-
47-
sub := tree.Add(bstr)
48-
for i, child := range c.Children {
49-
if child != nil {
50-
t.string(sub, child, i)
51-
}
52-
}
53-
case *node.Leaf:
54-
buffer := pools.EncodingBuffers.Get().(*bytes.Buffer)
55-
buffer.Reset()
56-
57-
_ = c.Encode(buffer)
58-
59-
encoding := buffer.Bytes()
60-
61-
var bstr string
62-
if len(encoding) > 1024 {
63-
bstr = fmt.Sprintf("idx=%d %s hash=%x gen=%d",
64-
idx, c.String(), common.MustBlake2bHash(encoding), c.GetGeneration())
65-
} else {
66-
bstr = fmt.Sprintf("idx=%d %s encode=%x gen=%d", idx, c.String(), encoding, c.GetGeneration())
67-
}
68-
69-
pools.EncodingBuffers.Put(buffer)
70-
71-
tree.Add(bstr)
72-
default:
73-
return
74-
}
12+
return t.root.String()
7513
}

0 commit comments

Comments
 (0)