Fixed merkle implementation to fit official algorithm.
This commit is contained in:
parent
7032d3b84a
commit
795e183273
169
merkle/iavl.go
169
merkle/iavl.go
|
@ -1,6 +1,7 @@
|
||||||
package merkle
|
package merkle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
//"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
)
|
)
|
||||||
|
@ -100,18 +101,19 @@ func (self *IAVLNode) Get(key Sortable) (value interface{}, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies and pops node from the tree.
|
// Returns a new tree (unless node is the root) & a copy of the popped node.
|
||||||
// Returns a new tree (unless node is the root) & new (popped) node.
|
// Can only pop nodes that have one or no children.
|
||||||
func (self *IAVLNode) pop_node(node *IAVLNode) (new_self, new_node *IAVLNode) {
|
func (self *IAVLNode) pop_node(node *IAVLNode) (new_self, new_node *IAVLNode) {
|
||||||
if node == nil {
|
if self == nil {
|
||||||
|
panic("self can't be nil")
|
||||||
|
} else if node == nil {
|
||||||
panic("node can't be nil")
|
panic("node can't be nil")
|
||||||
} else if node.left != nil && node.right != nil {
|
} else if node.left != nil && node.right != nil {
|
||||||
panic("node must not have both left and right")
|
panic("node must not have both left and right")
|
||||||
}
|
}
|
||||||
|
|
||||||
if self == nil {
|
if self == node {
|
||||||
return nil, node.Copy(true)
|
|
||||||
} else if self == node {
|
|
||||||
var n *IAVLNode
|
var n *IAVLNode
|
||||||
if node.left != nil {
|
if node.left != nil {
|
||||||
n = node.left
|
n = node.left
|
||||||
|
@ -124,18 +126,19 @@ func (self *IAVLNode) pop_node(node *IAVLNode) (new_self, new_node *IAVLNode) {
|
||||||
node.left = nil
|
node.left = nil
|
||||||
node.right = nil
|
node.right = nil
|
||||||
return n, node
|
return n, node
|
||||||
}
|
|
||||||
|
} else {
|
||||||
|
|
||||||
self = self.Copy(false)
|
self = self.Copy(false)
|
||||||
|
|
||||||
if node.key.Less(self.key) {
|
if node.key.Less(self.key) {
|
||||||
self.left, node = self.left.pop_node(node)
|
self.left, node = self.left.pop_node(node)
|
||||||
} else {
|
} else {
|
||||||
self.right, node = self.right.pop_node(node)
|
self.right, node = self.right.pop_node(node)
|
||||||
}
|
}
|
||||||
|
self.calc_height()
|
||||||
self.height = max(self.left.Height(), self.right.Height()) + 1
|
|
||||||
return self, node
|
return self, node
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pushes the node to the tree, returns a new tree
|
// Pushes the node to the tree, returns a new tree
|
||||||
|
@ -156,51 +159,74 @@ func (self *IAVLNode) push_node(node *IAVLNode) *IAVLNode {
|
||||||
} else {
|
} else {
|
||||||
self.right = self.right.push_node(node)
|
self.right = self.right.push_node(node)
|
||||||
}
|
}
|
||||||
self.height = max(self.left.Height(), self.right.Height()) + 1
|
self.calc_height()
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) rotate_right() *IAVLNode {
|
func (self *IAVLNode) rotate_right() *IAVLNode {
|
||||||
if self == nil {
|
self = self.Copy(false)
|
||||||
return self
|
sl := self.left.Copy(false)
|
||||||
}
|
slr := sl.right
|
||||||
if self.left == nil {
|
|
||||||
return self
|
sl.right = self
|
||||||
}
|
self.left = slr
|
||||||
return self.rotate(self.left.rmd)
|
|
||||||
|
self.calc_height()
|
||||||
|
sl.calc_height()
|
||||||
|
|
||||||
|
return sl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) rotate_left() *IAVLNode {
|
func (self *IAVLNode) rotate_left() *IAVLNode {
|
||||||
if self == nil {
|
self = self.Copy(false)
|
||||||
return self
|
sr := self.right.Copy(false)
|
||||||
}
|
srl := sr.left
|
||||||
if self.right == nil {
|
|
||||||
return self
|
sr.left = self
|
||||||
}
|
self.right = srl
|
||||||
return self.rotate(self.right.lmd)
|
|
||||||
|
self.calc_height()
|
||||||
|
sr.calc_height()
|
||||||
|
|
||||||
|
return sr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) rotate(get_new_root func() *IAVLNode) *IAVLNode {
|
func (self *IAVLNode) calc_height() {
|
||||||
self, new_root := self.pop_node(get_new_root())
|
self.height = max(self.left.Height(), self.right.Height()) + 1
|
||||||
new_root.left = self.left
|
|
||||||
new_root.right = self.right
|
|
||||||
self.hash = nil
|
|
||||||
self.left = nil
|
|
||||||
self.right = nil
|
|
||||||
return new_root.push_node(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) balance() *IAVLNode {
|
func (self *IAVLNode) calc_balance() int {
|
||||||
if self == nil {
|
if self == nil {
|
||||||
return self
|
return 0
|
||||||
}
|
}
|
||||||
for abs(self.left.Height() - self.right.Height()) > 2 {
|
return self.left.Height() - self.right.Height()
|
||||||
if self.left.Height() > self.right.Height() {
|
}
|
||||||
self = self.rotate_right()
|
|
||||||
|
func (self *IAVLNode) balance() (new_self *IAVLNode) {
|
||||||
|
balance := self.calc_balance()
|
||||||
|
if (balance > 1) {
|
||||||
|
if (self.left.calc_balance() >= 0) {
|
||||||
|
// Left Left Case
|
||||||
|
return self.rotate_right()
|
||||||
} else {
|
} else {
|
||||||
self = self.rotate_left()
|
// Left Right Case
|
||||||
|
self = self.Copy(false)
|
||||||
|
self.left = self.left.rotate_left()
|
||||||
|
return self.rotate_right()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (balance < -1) {
|
||||||
|
if (self.right.calc_balance() <= 0) {
|
||||||
|
// Right Right Case
|
||||||
|
return self.rotate_left()
|
||||||
|
} else {
|
||||||
|
// Right Left Case
|
||||||
|
self = self.Copy(false)
|
||||||
|
self.right = self.right.rotate_right()
|
||||||
|
return self.rotate_left()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Nothing changed
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,31 +248,29 @@ func (self *IAVLNode) Put(key Sortable, value interface{}) (_ *IAVLNode, updated
|
||||||
} else {
|
} else {
|
||||||
self.right, updated = self.right.Put(key, value)
|
self.right, updated = self.right.Put(key, value)
|
||||||
}
|
}
|
||||||
self.height = max(self.left.Height(), self.right.Height()) + 1
|
if updated {
|
||||||
|
return self, updated
|
||||||
if !updated {
|
} else {
|
||||||
self.height += 1
|
self.calc_height()
|
||||||
return self.balance(), updated
|
return self.balance(), updated
|
||||||
}
|
}
|
||||||
return self, updated
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Remove(key Sortable) (_ *IAVLNode, value interface{}, err error) {
|
func (self *IAVLNode) Remove(key Sortable) (new_self *IAVLNode, value interface{}, err error) {
|
||||||
if self == nil {
|
if self == nil {
|
||||||
return nil, nil, NotFound(key)
|
return nil, nil, NotFound(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.key.Equals(key) {
|
if self.key.Equals(key) {
|
||||||
if self.left != nil && self.right != nil {
|
if self.left != nil && self.right != nil {
|
||||||
var new_root *IAVLNode
|
|
||||||
if self.left.Size() < self.right.Size() {
|
if self.left.Size() < self.right.Size() {
|
||||||
self, new_root = self.pop_node(self.right.lmd())
|
self, new_self = self.pop_node(self.right.lmd())
|
||||||
} else {
|
} else {
|
||||||
self, new_root = self.pop_node(self.left.rmd())
|
self, new_self = self.pop_node(self.left.rmd())
|
||||||
}
|
}
|
||||||
new_root.left = self.left
|
new_self.left = self.left
|
||||||
new_root.right = self.right
|
new_self.right = self.right
|
||||||
return new_root, self.value, nil
|
return new_self, self.value, nil
|
||||||
} else if self.left == nil {
|
} else if self.left == nil {
|
||||||
return self.right, self.value, nil
|
return self.right, self.value, nil
|
||||||
} else if self.right == nil {
|
} else if self.right == nil {
|
||||||
|
@ -256,20 +280,35 @@ func (self *IAVLNode) Remove(key Sortable) (_ *IAVLNode, value interface{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self = self.Copy(true)
|
|
||||||
|
|
||||||
if key.Less(self.key) {
|
if key.Less(self.key) {
|
||||||
self.left, value, err = self.left.Remove(key)
|
if self.left == nil {
|
||||||
} else {
|
return self, nil, NotFound(key)
|
||||||
self.right, value, err = self.right.Remove(key)
|
|
||||||
}
|
}
|
||||||
if err == nil {
|
var new_left *IAVLNode
|
||||||
self.hash = nil
|
new_left, value, err = self.left.Remove(key)
|
||||||
self.height = max(self.left.Height(), self.right.Height()) + 1
|
if new_left == self.left { // not found
|
||||||
return self.balance(), value, err
|
return self, nil, err
|
||||||
} else {
|
} else if err != nil { // some other error
|
||||||
return self, value, err
|
return self, value, err
|
||||||
}
|
}
|
||||||
|
self = self.Copy(false)
|
||||||
|
self.left = new_left
|
||||||
|
} else {
|
||||||
|
if self.right == nil {
|
||||||
|
return self, nil, NotFound(key)
|
||||||
|
}
|
||||||
|
var new_right *IAVLNode
|
||||||
|
new_right, value, err = self.right.Remove(key)
|
||||||
|
if new_right == self.right { // not found
|
||||||
|
return self, nil, err
|
||||||
|
} else if err != nil { // some other error
|
||||||
|
return self, value, err
|
||||||
|
}
|
||||||
|
self = self.Copy(false)
|
||||||
|
self.right = new_right
|
||||||
|
}
|
||||||
|
self.calc_height()
|
||||||
|
return self.balance(), value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Height() int {
|
func (self *IAVLNode) Height() int {
|
||||||
|
@ -296,16 +335,12 @@ func (self *IAVLNode) Value() interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Left() Node {
|
func (self *IAVLNode) Left() Node {
|
||||||
if self.left == nil {
|
if self.left == nil { return nil }
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return self.left
|
return self.left
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *IAVLNode) Right() Node {
|
func (self *IAVLNode) Right() Node {
|
||||||
if self.right == nil {
|
if self.right == nil { return nil }
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return self.right
|
return self.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package merkle
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
@ -150,14 +151,6 @@ func TestTraversals(t *testing.T) {
|
||||||
var order []int = []int{
|
var order []int = []int{
|
||||||
6, 1, 8, 2, 4 , 9 , 5 , 7 , 0 , 3 ,
|
6, 1, 8, 2, 4 , 9 , 5 , 7 , 0 , 3 ,
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
var preorder []int = []int {
|
|
||||||
17, 7, 5, 1, 12, 9, 13, 19, 18, 20,
|
|
||||||
}
|
|
||||||
var postorder []int = []int {
|
|
||||||
1, 5, 9, 13, 12, 7, 18, 20, 19, 17,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
test := func(T Tree) {
|
test := func(T Tree) {
|
||||||
t.Logf("%T", T)
|
t.Logf("%T", T)
|
||||||
|
@ -177,24 +170,106 @@ func TestTraversals(t *testing.T) {
|
||||||
}
|
}
|
||||||
j += 1
|
j += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
j = 0
|
|
||||||
for tn, next := tree.TraverseTreePreOrder(T.Root())(); next != nil; tn, next = next () {
|
|
||||||
if int(tn.Key().(Int)) != preorder[j] {
|
|
||||||
t.Error("key in wrong spot pre-order")
|
|
||||||
}
|
|
||||||
j += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
j = 0
|
|
||||||
for tn, next := tree.TraverseTreePostOrder(T.Root())(); next != nil; tn, next = next () {
|
|
||||||
if int(tn.Key().(Int)) != postorder[j] {
|
|
||||||
t.Error("key in wrong spot post-order")
|
|
||||||
}
|
|
||||||
j += 1
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
test(NewIAVLTree())
|
test(NewIAVLTree())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkSha256(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
|
||||||
|
str := []byte(randstr(32))
|
||||||
|
|
||||||
|
ransha256 := func() []byte {
|
||||||
|
return CalcSha256(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ransha256()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from http://stackoverflow.com/questions/3955680/how-to-check-if-my-avl-tree-implementation-is-correct
|
||||||
|
func TestGriffin(t *testing.T) {
|
||||||
|
N := func(l *IAVLNode, i int, r *IAVLNode) *IAVLNode {
|
||||||
|
n := &IAVLNode{Int32(i), nil, -1, nil, l, r}
|
||||||
|
n.calc_height()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
var P func(*IAVLNode) string
|
||||||
|
P = func(n *IAVLNode) string {
|
||||||
|
if n.left == nil && n.right == nil {
|
||||||
|
return fmt.Sprintf("%v", n.key)
|
||||||
|
} else if n.left == nil {
|
||||||
|
return fmt.Sprintf("(- %v %v)", n.key, P(n.right))
|
||||||
|
} else if n.right == nil {
|
||||||
|
return fmt.Sprintf("(%v %v -)", P(n.left), n.key)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("(%v %v %v)", P(n.left), n.key, P(n.right))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectPut := func(n *IAVLNode, i int, repr string) {
|
||||||
|
n2, updated := n.Put(Int32(i), nil)
|
||||||
|
if updated == true || P(n2) != repr {
|
||||||
|
t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v",
|
||||||
|
i, P(n), repr, P(n2), updated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectRemove := func(n *IAVLNode, i int, repr string) {
|
||||||
|
n2, value, err := n.Remove(Int32(i))
|
||||||
|
if value != nil || err != nil || P(n2) != repr {
|
||||||
|
t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v err:%v",
|
||||||
|
i, P(n), repr, P(n2), value, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// Test Put cases:
|
||||||
|
|
||||||
|
// Case 1:
|
||||||
|
n1 := N(N(nil, 4, nil), 20, nil)
|
||||||
|
if P(n1) != "(4 20 -)" { t.Fatalf("Got %v", P(n1)) }
|
||||||
|
|
||||||
|
expectPut(n1, 15, "(4 15 20)")
|
||||||
|
expectPut(n1, 8, "(4 8 20)")
|
||||||
|
|
||||||
|
// Case 2:
|
||||||
|
n2 := N(N(N(nil, 3, nil), 4, N(nil, 9, nil)), 20, N(nil, 26, nil))
|
||||||
|
if P(n2) != "((3 4 9) 20 26)" { t.Fatalf("Got %v", P(n2)) }
|
||||||
|
|
||||||
|
expectPut(n2, 15, "((3 4 -) 9 (15 20 26))")
|
||||||
|
expectPut(n2, 8, "((3 4 8) 9 (- 20 26))")
|
||||||
|
|
||||||
|
// Case 2:
|
||||||
|
n3 := N(N(N(N(nil, 2, nil), 3, nil), 4, N(N(nil, 7, nil), 9, N(nil, 11, nil))),
|
||||||
|
20, N(N(nil, 21, nil), 26, N(nil, 30, nil)))
|
||||||
|
if P(n3) != "(((2 3 -) 4 (7 9 11)) 20 (21 26 30))" { t.Fatalf("Got %v", P(n3)) }
|
||||||
|
|
||||||
|
expectPut(n3, 15, "(((2 3 -) 4 7) 9 ((- 11 15) 20 (21 26 30)))")
|
||||||
|
expectPut(n3, 8, "(((2 3 -) 4 (- 7 8)) 9 (11 20 (21 26 30)))")
|
||||||
|
|
||||||
|
|
||||||
|
//////// Test Remove cases:
|
||||||
|
|
||||||
|
// Case 4:
|
||||||
|
n4 := N(N(nil, 1, nil), 2, N(N(nil, 3, nil), 4, N(nil, 5, nil)))
|
||||||
|
if P(n4) != "(1 2 (3 4 5))" { t.Fatalf("Got %v", P(n4)) }
|
||||||
|
|
||||||
|
expectRemove(n4, 1, "((- 2 3) 4 5)")
|
||||||
|
|
||||||
|
// Case 5:
|
||||||
|
n5 := N(N(N(nil, 1, nil), 2, N(N(nil, 3, nil), 4, N(nil, 5, nil))), 6,
|
||||||
|
N(N(N(nil, 7, nil), 8, nil), 9, N(N(nil, 10, nil), 11, N(nil, 12, N(nil, 13, nil)))))
|
||||||
|
if P(n5) != "((1 2 (3 4 5)) 6 ((7 8 -) 9 (10 11 (- 12 13))))" { t.Fatalf("Got %v", P(n5)) }
|
||||||
|
|
||||||
|
expectRemove(n5, 1, "(((- 2 3) 4 5) 6 ((7 8 -) 9 (10 11 (- 12 13))))")
|
||||||
|
|
||||||
|
// Case 6:
|
||||||
|
n6 := N(N(N(nil, 1, nil), 2, N(nil, 3, N(nil, 4, nil))), 5,
|
||||||
|
N(N(N(nil, 6, nil), 7, nil), 8, N(N(nil, 9, nil), 10, N(nil, 11, N(nil, 12, nil)))))
|
||||||
|
if P(n6) != "((1 2 (- 3 4)) 5 ((6 7 -) 8 (9 10 (- 11 12))))" { t.Fatalf("Got %v", P(n6)) }
|
||||||
|
|
||||||
|
expectRemove(n6, 1, "(((2 3 4) 5 (6 7 -)) 8 (9 10 (- 11 12)))")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ type Node interface {
|
||||||
Size() int
|
Size() int
|
||||||
Has(key Sortable) bool
|
Has(key Sortable) bool
|
||||||
Get(key Sortable) (value interface{}, err error)
|
Get(key Sortable) (value interface{}, err error)
|
||||||
|
|
||||||
|
Put(key Sortable, value interface{}) (_ *IAVLNode, updated bool)
|
||||||
|
Remove(key Sortable) (_ *IAVLNode, value interface{}, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeIterator func() (node Node, next NodeIterator)
|
type NodeIterator func() (node Node, next NodeIterator)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package merkle
|
package merkle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
func Iterator(node Node) NodeIterator {
|
func Iterator(node Node) NodeIterator {
|
||||||
stack := make([]Node, 0, 10)
|
stack := make([]Node, 0, 10)
|
||||||
var cur Node = node
|
var cur Node = node
|
||||||
|
@ -28,3 +32,23 @@ func pop(stack []Node) ([]Node, Node) {
|
||||||
return stack[0:len(stack)-1], stack[len(stack)-1]
|
return stack[0:len(stack)-1], stack[len(stack)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrintIAVLNode(node *IAVLNode) {
|
||||||
|
fmt.Println("==== NODE")
|
||||||
|
printIAVLNode(node, 0)
|
||||||
|
fmt.Println("==== END")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printIAVLNode(node *IAVLNode, indent int) {
|
||||||
|
indentPrefix := ""
|
||||||
|
for i:=0; i<indent; i++ {
|
||||||
|
indentPrefix += " "
|
||||||
|
}
|
||||||
|
if node == nil {
|
||||||
|
fmt.Printf("%s--\n", indentPrefix)
|
||||||
|
} else {
|
||||||
|
printIAVLNode(node.left, indent+1)
|
||||||
|
fmt.Printf("%s%v:%v\n", indentPrefix, node.key, node.height)
|
||||||
|
printIAVLNode(node.right, indent+1)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue