mirror of https://github.com/status-im/op-geth.git
Fixed an issue where the trie might crash on missmatching lengths
This commit is contained in:
parent
5ec62a5153
commit
09bade6466
|
@ -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{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
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
|
||||||
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{} {
|
||||||
// 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{} {
|
||||||
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 (
|
||||||
"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) {
|
||||||
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, 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) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue