diff --git a/ptrie/cache.go b/ptrie/cache.go new file mode 100644 index 000000000..8efdb047b --- /dev/null +++ b/ptrie/cache.go @@ -0,0 +1,42 @@ +package ptrie + +type Backend interface { + Get([]byte) []byte + Set([]byte, []byte) +} + +type Cache struct { + store map[string][]byte + backend Backend +} + +func NewCache(backend Backend) *Cache { + return &Cache{make(map[string][]byte), backend} +} + +func (self *Cache) Get(key []byte) []byte { + data := self.store[string(key)] + if data == nil { + data = self.backend.Get(key) + } + + return data +} + +func (self *Cache) Set(key []byte, data []byte) { + self.store[string(key)] = data +} + +func (self *Cache) Flush() { + for k, v := range self.store { + self.backend.Set([]byte(k), v) + } + + // This will eventually grow too large. We'd could + // do a make limit on storage and push out not-so-popular nodes. + //self.Reset() +} + +func (self *Cache) Reset() { + self.store = make(map[string][]byte) +} diff --git a/ptrie/trie.go b/ptrie/trie.go index 687126aef..0ef498b10 100644 --- a/ptrie/trie.go +++ b/ptrie/trie.go @@ -10,47 +10,6 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -type Backend interface { - Get([]byte) []byte - Set([]byte, []byte) -} - -type Cache struct { - store map[string][]byte - backend Backend -} - -func NewCache(backend Backend) *Cache { - return &Cache{make(map[string][]byte), backend} -} - -func (self *Cache) Get(key []byte) []byte { - data := self.store[string(key)] - if data == nil { - data = self.backend.Get(key) - } - - return data -} - -func (self *Cache) Set(key []byte, data []byte) { - self.store[string(key)] = data -} - -func (self *Cache) Flush() { - for k, v := range self.store { - self.backend.Set([]byte(k), v) - } - - // This will eventually grow too large. We'd could - // do a make limit on storage and push out not-so-popular nodes. - //self.Reset() -} - -func (self *Cache) Reset() { - self.store = make(map[string][]byte) -} - type Trie struct { mu sync.Mutex root Node @@ -83,14 +42,17 @@ func (self *Trie) Root() []byte { return self.Hash() } func (self *Trie) Hash() []byte { var hash []byte if self.root != nil { - t := self.root.Hash() - if byts, ok := t.([]byte); ok { - hash = byts - } else { - hash = crypto.Sha3(ethutil.Encode(self.root.RlpData())) - } + hash = self.root.Hash().([]byte) + /* + t := self.root.Hash() + if byts, ok := t.([]byte); ok { + hash = byts + } else { + hash = crypto.Sha3(ethutil.Encode(self.root.RlpData())) + } + */ } else { - hash = crypto.Sha3(ethutil.Encode(self.root)) + hash = crypto.Sha3(ethutil.Encode("")) } if !bytes.Equal(hash, self.roothash) { @@ -107,6 +69,7 @@ func (self *Trie) Commit() { self.cache.Flush() } +// Reset should only be called if the trie has been hashed func (self *Trie) Reset() { self.cache.Reset() diff --git a/ptrie/trie_test.go b/ptrie/trie_test.go index 478f59c60..aed16a2ff 100644 --- a/ptrie/trie_test.go +++ b/ptrie/trie_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" ) @@ -18,6 +19,15 @@ func NewEmpty() *Trie { return New(nil, make(Db)) } +func TestEmptyTrie(t *testing.T) { + trie := NewEmpty() + res := trie.Hash() + exp := crypto.Sha3(ethutil.Encode("")) + if !bytes.Equal(res, exp) { + t.Errorf("expected %x got %x", exp, res) + } +} + func TestInsert(t *testing.T) { trie := NewEmpty() @@ -62,6 +72,34 @@ func TestGet(t *testing.T) { func TestDelete(t *testing.T) { trie := NewEmpty() + vals := []struct{ k, v string }{ + {"do", "verb"}, + {"ether", "wookiedoo"}, + {"horse", "stallion"}, + {"shaman", "horse"}, + {"doge", "coin"}, + {"ether", ""}, + {"dog", "puppy"}, + {"shaman", ""}, + } + for _, val := range vals { + if val.v != "" { + trie.UpdateString(val.k, val.v) + } else { + trie.DeleteString(val.k) + } + } + + hash := trie.Hash() + exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84") + if !bytes.Equal(hash, exp) { + t.Errorf("expected %x got %x", exp, hash) + } +} + +func TestEmptyValues(t *testing.T) { + trie := NewEmpty() + vals := []struct{ k, v string }{ {"do", "verb"}, {"ether", "wookiedoo"}, @@ -142,7 +180,7 @@ func TestReset(t *testing.T) { } } -// Not actual test +// Not an actual test func TestOutput(t *testing.T) { t.Skip()