good morning!!!!

Skip to content
Snippets Groups Projects
Commit 09bade64 authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

Fixed an issue where the trie might crash on missmatching lengths

parent 5ec62a51
Branches
Tags
No related merge requests found
...@@ -9,6 +9,8 @@ import ( ...@@ -9,6 +9,8 @@ import (
"sync" "sync"
) )
func __ignore() { fmt.Println("") }
func ParanoiaCheck(t1 *Trie) (bool, *Trie) { func ParanoiaCheck(t1 *Trie) (bool, *Trie) {
t2 := NewTrie(ethutil.Config.Db, "") t2 := NewTrie(ethutil.Config.Db, "")
...@@ -269,8 +271,7 @@ func (t *Trie) getState(node interface{}, key []int) interface{} { ...@@ -269,8 +271,7 @@ func (t *Trie) getState(node interface{}, key []int) interface{} {
} }
// It shouldn't come this far // It shouldn't come this far
fmt.Println("getState unexpected return") panic("unexpected return")
return ""
} }
func (t *Trie) getNode(node interface{}) *ethutil.Value { func (t *Trie) getNode(node interface{}) *ethutil.Value {
...@@ -287,7 +288,9 @@ func (t *Trie) getNode(node interface{}) *ethutil.Value { ...@@ -287,7 +288,9 @@ func (t *Trie) getNode(node interface{}) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte(str)) return ethutil.NewValueFromBytes([]byte(str))
} }
return t.cache.Get(n.Bytes()) data := t.cache.Get(n.Bytes())
return data
} }
func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{} { func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{} {
...@@ -385,7 +388,7 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter ...@@ -385,7 +388,7 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
return t.Put(newNode) return t.Put(newNode)
} }
return "" panic("unexpected end")
} }
func (t *Trie) deleteState(node interface{}, key []int) interface{} { func (t *Trie) deleteState(node interface{}, key []int) interface{} {
...@@ -396,6 +399,7 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} { ...@@ -396,6 +399,7 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
// New node // New node
n := ethutil.NewValue(node) n := ethutil.NewValue(node)
if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 { if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
//return nil
return "" return ""
} }
...@@ -406,12 +410,17 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} { ...@@ -406,12 +410,17 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
k := CompactDecode(currentNode.Get(0).Str()) k := CompactDecode(currentNode.Get(0).Str())
v := currentNode.Get(1).Raw() v := currentNode.Get(1).Raw()
matchingLength := MatchingNibbleLength(key, k)
// Matching key pair (ie. there's already an object with this key) // Matching key pair (ie. there's already an object with this key)
if CompareIntSlice(k, key) { if CompareIntSlice(k, key) {
return "" return ""
} else if CompareIntSlice(key[:len(k)], k) { } else if CompareIntSlice(key[:matchingLength], k) {
hash := t.deleteState(v, key[len(k):]) hash := t.deleteState(v, key[len(k):])
child := t.getNode(hash) child := t.getNode(hash)
if child.IsNil() {
return node
}
var newNode []interface{} var newNode []interface{}
if child.Len() == 2 { if child.Len() == 2 {
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/ethereum/eth-go/ethutil"
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"net/http" "net/http"
...@@ -251,8 +252,8 @@ func TestRemote(t *testing.T) { ...@@ -251,8 +252,8 @@ func TestRemote(t *testing.T) {
trie.Update(get(key), get(value)) trie.Update(get(key), get(value))
} }
a := NewValue(h(test.Root)).Bytes() a := ethutil.NewValue(h(test.Root)).Bytes()
b := NewValue(trie.Root).Bytes() b := ethutil.NewValue(trie.Root).Bytes()
if bytes.Compare(a, b) != 0 { if bytes.Compare(a, b) != 0 {
t.Errorf("%-10s: %x %x", test.Name, a, b) t.Errorf("%-10s: %x %x", test.Name, a, b)
} }
...@@ -267,12 +268,12 @@ func TestTrieReplay(t *testing.T) { ...@@ -267,12 +268,12 @@ func TestTrieReplay(t *testing.T) {
} }
_, trie2 := New() _, trie2 := New()
trie.NewIterator().Each(func(key string, v *Value) { trie.NewIterator().Each(func(key string, v *ethutil.Value) {
trie2.Update(key, v.Str()) trie2.Update(key, v.Str())
}) })
a := NewValue(trie.Root).Bytes() a := ethutil.NewValue(trie.Root).Bytes()
b := NewValue(trie2.Root).Bytes() b := ethutil.NewValue(trie2.Root).Bytes()
if bytes.Compare(a, b) != 0 { if bytes.Compare(a, b) != 0 {
t.Errorf("%s %x %x\n", test.Name, trie.Root, trie2.Root) t.Errorf("%s %x %x\n", test.Name, trie.Root, trie2.Root)
} }
...@@ -329,3 +330,38 @@ func TestRegression(t *testing.T) { ...@@ -329,3 +330,38 @@ func TestRegression(t *testing.T) {
} }
} }
} }
func TestDelete(t *testing.T) {
_, trie := New()
trie.Update("a", "jeffreytestlongstring")
trie.Update("aa", "otherstring")
trie.Update("aaa", "othermorestring")
trie.Update("aabbbbccc", "hithere")
trie.Update("abbcccdd", "hstanoehutnaheoustnh")
trie.Update("rnthaoeuabbcccdd", "hstanoehutnaheoustnh")
trie.Update("rneuabbcccdd", "hstanoehutnaheoustnh")
trie.Update("rneuabboeusntahoeucccdd", "hstanoehutnaheoustnh")
trie.Update("rnxabboeusntahoeucccdd", "hstanoehutnaheoustnh")
trie.Delete("aaboaestnuhbccc")
trie.Delete("a")
trie.Update("a", "nthaonethaosentuh")
trie.Update("c", "shtaosntehua")
trie.Delete("a")
trie.Update("aaaa", "testmegood")
fmt.Println("aa =>", trie.Get("aa"))
_, t2 := New()
trie.NewIterator().Each(func(key string, v *ethutil.Value) {
if key == "aaaa" {
t2.Update(key, v.Str())
} else {
t2.Update(key, v.Str())
}
})
a := ethutil.NewValue(trie.Root).Bytes()
b := ethutil.NewValue(t2.Root).Bytes()
fmt.Printf("o: %x\nc: %x\n", a, b)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment