Added paranoia check for tries

This commit is contained in:
obscuren 2014-11-19 16:56:01 +01:00
parent cab7e6000e
commit b05e63c34d
3 changed files with 48 additions and 10 deletions

View File

@ -1,8 +1,8 @@
package ptrie package ptrie
type Backend interface { type Backend interface {
Get([]byte) []byte Get([]byte) ([]byte, error)
Set([]byte, []byte) Put([]byte, []byte)
} }
type Cache struct { type Cache struct {
@ -17,19 +17,19 @@ func NewCache(backend Backend) *Cache {
func (self *Cache) Get(key []byte) []byte { func (self *Cache) Get(key []byte) []byte {
data := self.store[string(key)] data := self.store[string(key)]
if data == nil { if data == nil {
data = self.backend.Get(key) data, _ = self.backend.Get(key)
} }
return data return data
} }
func (self *Cache) Set(key []byte, data []byte) { func (self *Cache) Put(key []byte, data []byte) {
self.store[string(key)] = data self.store[string(key)] = data
} }
func (self *Cache) Flush() { func (self *Cache) Flush() {
for k, v := range self.store { for k, v := range self.store {
self.backend.Set([]byte(k), v) self.backend.Put([]byte(k), v)
} }
// This will eventually grow too large. We'd could // This will eventually grow too large. We'd could

View File

@ -10,6 +10,17 @@ import (
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) {
t2 := New(nil, backend)
it := t1.Iterator()
for it.Next() {
t2.Update(it.Key, it.Value)
}
return bytes.Compare(t2.Hash(), t1.Hash()) == 0, t2
}
type Trie struct { type Trie struct {
mu sync.Mutex mu sync.Mutex
root Node root Node
@ -293,7 +304,7 @@ func (self *Trie) store(node Node) interface{} {
data := ethutil.Encode(node) data := ethutil.Encode(node)
if len(data) >= 32 { if len(data) >= 32 {
key := crypto.Sha3(data) key := crypto.Sha3(data)
self.cache.Set(key, data) self.cache.Put(key, data)
return key return key
} }

View File

@ -11,8 +11,8 @@ import (
type Db map[string][]byte type Db map[string][]byte
func (self Db) Get(k []byte) []byte { return self[string(k)] } func (self Db) Get(k []byte) ([]byte, error) { return self[string(k)], nil }
func (self Db) Set(k, v []byte) { self[string(k)] = v } func (self Db) Put(k, v []byte) { self[string(k)] = v }
// Used for testing // Used for testing
func NewEmpty() *Trie { func NewEmpty() *Trie {
@ -122,6 +122,7 @@ func TestEmptyValues(t *testing.T) {
} }
func TestReplication(t *testing.T) { func TestReplication(t *testing.T) {
t.Skip()
trie := NewEmpty() trie := NewEmpty()
vals := []struct{ k, v string }{ vals := []struct{ k, v string }{
{"do", "verb"}, {"do", "verb"},
@ -139,7 +140,7 @@ func TestReplication(t *testing.T) {
} }
trie.Hash() trie.Hash()
trie2 := New(trie.roothash, trie.cache) trie2 := New(trie.roothash, trie.cache.backend)
if string(trie2.GetString("horse")) != "stallion" { if string(trie2.GetString("horse")) != "stallion" {
t.Error("expected to have harse => stallion") t.Error("expected to have harse => stallion")
} }
@ -180,6 +181,32 @@ func TestReset(t *testing.T) {
} }
} }
func TestParanoia(t *testing.T) {
t.Skip()
trie := NewEmpty()
vals := []struct{ k, v string }{
{"do", "verb"},
{"ether", "wookiedoo"},
{"horse", "stallion"},
{"shaman", "horse"},
{"doge", "coin"},
{"ether", ""},
{"dog", "puppy"},
{"shaman", ""},
{"somethingveryoddindeedthis is", "myothernodedata"},
}
for _, val := range vals {
trie.UpdateString(val.k, val.v)
}
trie.Commit()
ok, t2 := ParanoiaCheck(trie, trie.cache.backend)
if !ok {
t.Errorf("trie paranoia check failed %x %x", trie.roothash, t2.roothash)
}
}
// Not an actual test // Not an actual test
func TestOutput(t *testing.T) { func TestOutput(t *testing.T) {
t.Skip() t.Skip()
@ -193,7 +220,7 @@ func TestOutput(t *testing.T) {
fmt.Println("############################## FULL ################################") fmt.Println("############################## FULL ################################")
fmt.Println(trie.root) fmt.Println(trie.root)
trie2 := New(trie.roothash, trie.cache) trie2 := New(trie.roothash, trie.cache.backend)
trie2.GetString(base + "20") trie2.GetString(base + "20")
fmt.Println("############################## SMALL ################################") fmt.Println("############################## SMALL ################################")
fmt.Println(trie2.root) fmt.Println(trie2.root)