-
Notifications
You must be signed in to change notification settings - Fork 17
/
iavl_tree_dump.go
144 lines (119 loc) · 2.99 KB
/
iavl_tree_dump.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package iavl
import (
"bytes"
"fmt"
//"strings"
wire "github.com/tendermint/go-wire"
)
type Formatter func(in []byte) (out string)
type KeyValueMapping struct {
Key Formatter
Value Formatter
}
// Flip back and forth between ascii and hex.
func mixedDisplay(value []byte) string {
var buffer bytes.Buffer
var last []byte
ascii := true
for i := 0; i < len(value); i++ {
if value[i] < 32 || value[i] > 126 {
if ascii && len(last) > 0 {
// only if there are 6 or more chars
if len(last) > 5 {
buffer.WriteString(fmt.Sprintf("%s", last))
last = nil
}
ascii = false
}
}
last = append(last, value[i])
}
if ascii {
buffer.WriteString(fmt.Sprintf("%s", last))
} else {
buffer.WriteString(fmt.Sprintf("%X", last))
}
return buffer.String()
}
// This is merkleeyes state, that it is writing to a specific key
type state struct {
Hash []byte
Height uint64
}
// Try to interpet as merkleeyes state
func stateMapping(value []byte) string {
var s state
err := wire.ReadBinaryBytes(value, &s)
if err != nil || s.Height > 500 {
return mixedDisplay(value)
}
return fmt.Sprintf("Height:%d, [%X]", s.Height, s.Hash)
}
// This is basecoin accounts, that it is writing to a specific key
type account struct {
PubKey []byte
Sequence int
Balance []coin
}
type wrapper struct {
bytes []byte
}
type coin struct {
Denom string
Amount int64
}
// Perhaps this is an IAVL tree node?
func nodeMapping(node *IAVLNode) string {
formattedKey := mixedDisplay(node.key)
var formattedValue string
var acc account
err := wire.ReadBinaryBytes(node.value, &acc)
if err != nil {
formattedValue = mixedDisplay(node.value)
} else {
formattedValue = fmt.Sprintf("%v", acc)
}
if node.height == 0 {
return fmt.Sprintf(" LeafNode[height: %d, size %d, key: %s, value: %s]",
node.height, node.size, formattedKey, formattedValue)
} else {
return fmt.Sprintf("InnerNode[height: %d, size %d, key: %s, leftHash: %X, rightHash: %X]",
node.height, node.size, formattedKey, node.leftHash, node.rightHash)
}
}
// Try everything and see what sticks...
func overallMapping(value []byte) (str string) {
// underneath make node, wire can throw a panic
defer func() {
if recover() != nil {
str = fmt.Sprintf("%X", value)
return
}
}()
// test to see if this is a node
node, err := MakeIAVLNode(value, nil)
if err == nil && node.height < 100 && node.key != nil {
return nodeMapping(node)
}
// Unknown value type
return stateMapping(value)
}
// Dump everything from the database
func (t *IAVLTree) Dump(verbose bool, mapping *KeyValueMapping) {
if verbose && t.root == nil {
fmt.Printf("No root loaded into memory\n")
}
if mapping == nil {
mapping = &KeyValueMapping{Key: mixedDisplay, Value: overallMapping}
}
if verbose {
stats := t.ndb.db.Stats()
for key, value := range stats {
fmt.Printf("%s:\n\t%s\n", key, value)
}
}
iter := t.ndb.db.Iterator()
for iter.Next() {
fmt.Printf("%s: %s\n", mapping.Key(iter.Key()), mapping.Value(iter.Value()))
}
}