-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
152 lines (121 loc) · 3.88 KB
/
main.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
145
146
147
148
149
150
151
152
package main
import (
"crypto/sha256"
"errors"
"fmt"
)
type merkleNode struct {
isLeaf bool
hash string
leftChild *merkleNode
rightChild *merkleNode
}
func toSHA256(data string) string {
sum := sha256.Sum256([]byte(data))
return fmt.Sprintf("%x", sum)
}
func CreateMerkleTree(hashes []string) (merkleNode, error) {
numberHashes := len(hashes)
t := merkleNode{isLeaf: false, hash: "", leftChild: nil, rightChild: nil}
if numberHashes <= 0 {
return merkleNode{}, errors.New("Empty array of hashes")
}
if numberHashes > 0 {
for _, elt := range hashes {
t.AddNode(elt)
}
}
return t, nil
}
func (node *merkleNode) AddNode(data string) {
if node.leftChild == nil {
node.leftChild = &merkleNode{isLeaf: true, hash: toSHA256(data), leftChild: nil, rightChild: nil}
} else if node.rightChild == nil {
/*
If the left part of the current tree is complete
*/
if node.leftChild.isCompleteTree() {
node.rightChild = &merkleNode{isLeaf: false, hash: "", leftChild: nil, rightChild: nil}
height := node.GetHeight()
node.rightChild.insertLeft(height-1, data)
/*
Otherwise, just insert the node where we find a nil right child from this current part of the tree.
*/
} else {
node.leftChild.AddNode(data)
}
/*
If it's a complete tree, we need to add a new layer at the top of the tree,
then insert the node at the bottom right of this tree.
*/
} else if node.isCompleteTree() {
root := merkleNode{isLeaf: node.isLeaf, hash: node.hash, leftChild: node.leftChild, rightChild: node.rightChild}
node.leftChild = &root
node.rightChild = &merkleNode{isLeaf: false, hash: "", leftChild: nil, rightChild: nil}
height := node.GetHeight()
node.rightChild.insertLeft(height-1, data)
/*
Otherwise, just insert the node where we find a nil right child from this current part of the tree.
*/
} else {
node.rightChild.AddNode(data)
}
// Once the node is inserted, we need to recalculate the current node's hash
node.hashMe()
}
/*
Insert the node at a given level of a tree.
*/
func (node *merkleNode) insertLeft(level int, data string) {
if level == 0 {
node.isLeaf = true
node.hash = toSHA256(data)
return
}
node.leftChild = &merkleNode{isLeaf: false, hash: "", leftChild: nil, rightChild: nil}
node.leftChild.insertLeft(level-1, data)
node.hashMe()
}
func (node merkleNode) isCompleteTree() bool {
i := 0
height := node.GetHeight()
for i = 0; i < height && node.rightChild != nil; i++ {
node = *node.rightChild
}
return height == i
}
func (node *merkleNode) hashMe() {
if node.leftChild != nil && node.rightChild != nil {
node.hash = toSHA256(node.leftChild.hash + node.rightChild.hash)
} else if node.leftChild != nil && node.rightChild == nil {
node.hash = node.leftChild.hash
}
}
func (node merkleNode) GetRoot() string {
return node.hash
}
func (node merkleNode) GetHeight() (height int) {
for height = 0; !node.isLeaf && node.leftChild != nil; height++ {
node = *node.leftChild
}
return
}
func (node merkleNode) getNodesByLevel(level int) []string {
if level <= 0 {
return []string{node.hash}
} else {
if node.rightChild != nil {
return append(node.leftChild.getNodesByLevel(level-1), node.rightChild.getNodesByLevel(level-1)...)
}
return node.leftChild.getNodesByLevel(level - 1)
}
}
func (node merkleNode) GetLevel(level int) ([]string, error) {
height := node.GetHeight()
if level > height {
return nil, errors.New("Level too deep")
}
return node.getNodesByLevel(level), nil
}
func main() {
}