diff --git a/trie/cache.go b/trie/cache.go index e03702b255e26bd8bc0c3a69a9ce3635decd70bb..2143785faf3ed3c605df18b4eca400a76fa67a9e 100644 --- a/trie/cache.go +++ b/trie/cache.go @@ -37,6 +37,14 @@ func (self *Cache) Flush() { //self.Reset() } +func (self *Cache) Copy() *Cache { + cache := NewCache(self.backend) + for k, v := range self.store { + cache.store[k] = v + } + return cache +} + func (self *Cache) Reset() { - self.store = make(map[string][]byte) + //self.store = make(map[string][]byte) } diff --git a/trie/fullnode.go b/trie/fullnode.go index ebbe7f3844ffaee6e721ede003634026a73a4a44..522fdb373c5a4363a16c8f4ecf5f476301802554 100644 --- a/trie/fullnode.go +++ b/trie/fullnode.go @@ -20,11 +20,11 @@ func (self *FullNode) Branches() []Node { return self.nodes[:16] } -func (self *FullNode) Copy() Node { - nnode := NewFullNode(self.trie) +func (self *FullNode) Copy(t *Trie) Node { + nnode := NewFullNode(t) for i, node := range self.nodes { if node != nil { - nnode.nodes[i] = node + nnode.nodes[i] = node.Copy(t) } } diff --git a/trie/hashnode.go b/trie/hashnode.go index 40ccd54c31f85606a8b5e60f457820f15b2b9695..e46628368aef757f9350783f7baaf75198d15dc0 100644 --- a/trie/hashnode.go +++ b/trie/hashnode.go @@ -1,11 +1,14 @@ package trie +import "github.com/ethereum/go-ethereum/ethutil" + type HashNode struct { - key []byte + key []byte + trie *Trie } -func NewHash(key []byte) *HashNode { - return &HashNode{key} +func NewHash(key []byte, trie *Trie) *HashNode { + return &HashNode{key, trie} } func (self *HashNode) RlpData() interface{} { @@ -17,6 +20,6 @@ func (self *HashNode) Hash() interface{} { } // These methods will never be called but we have to satisfy Node interface -func (self *HashNode) Value() Node { return nil } -func (self *HashNode) Dirty() bool { return true } -func (self *HashNode) Copy() Node { return self } +func (self *HashNode) Value() Node { return nil } +func (self *HashNode) Dirty() bool { return true } +func (self *HashNode) Copy(t *Trie) Node { return NewHash(ethutil.CopyBytes(self.key), t) } diff --git a/trie/node.go b/trie/node.go index f28f2477100843cf16cfaed2d8f5577e448e16df..0d8a7cff9d1ba481421ead1e59c9d22ba001a816 100644 --- a/trie/node.go +++ b/trie/node.go @@ -6,7 +6,7 @@ var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b type Node interface { Value() Node - Copy() Node // All nodes, for now, return them self + Copy(*Trie) Node // All nodes, for now, return them self Dirty() bool fstring(string) string Hash() interface{} @@ -18,7 +18,11 @@ func (self *ValueNode) String() string { return self.fstring("") } func (self *FullNode) String() string { return self.fstring("") } func (self *ShortNode) String() string { return self.fstring("") } func (self *ValueNode) fstring(ind string) string { return fmt.Sprintf("%x ", self.data) } -func (self *HashNode) fstring(ind string) string { return fmt.Sprintf("< %x > ", self.key) } + +//func (self *HashNode) fstring(ind string) string { return fmt.Sprintf("< %x > ", self.key) } +func (self *HashNode) fstring(ind string) string { + return fmt.Sprintf("%v", self.trie.trans(self)) +} // Full node func (self *FullNode) fstring(ind string) string { diff --git a/trie/shortnode.go b/trie/shortnode.go index f132b56d96603a93b756d875d76763702bb4fabd..d96492958401614bea32b112a9ef7ee64d2e0f1f 100644 --- a/trie/shortnode.go +++ b/trie/shortnode.go @@ -1,5 +1,7 @@ package trie +import "github.com/ethereum/go-ethereum/ethutil" + type ShortNode struct { trie *Trie key []byte @@ -15,7 +17,11 @@ func (self *ShortNode) Value() Node { return self.value } func (self *ShortNode) Dirty() bool { return true } -func (self *ShortNode) Copy() Node { return NewShortNode(self.trie, self.key, self.value) } +func (self *ShortNode) Copy(t *Trie) Node { + node := &ShortNode{t, nil, self.value.Copy(t)} + node.key = ethutil.CopyBytes(self.key) + return node +} func (self *ShortNode) RlpData() interface{} { return []interface{}{self.key, self.value.Hash()} diff --git a/trie/trie.go b/trie/trie.go index 36f2af5d22c0cb2db1b13a2129b89e89fa2883e6..9087f7bdaaee3dd97c017549f9981385cc323809 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -34,7 +34,9 @@ func New(root []byte, backend Backend) *Trie { trie := &Trie{} trie.revisions = list.New() trie.roothash = root - trie.cache = NewCache(backend) + if backend != nil { + trie.cache = NewCache(backend) + } if root != nil { value := ethutil.NewValueFromBytes(trie.cache.Get(root)) @@ -49,7 +51,15 @@ func (self *Trie) Iterator() *Iterator { } func (self *Trie) Copy() *Trie { - return New(self.roothash, self.cache.backend) + cpy := make([]byte, 32) + copy(cpy, self.roothash) + trie := New(nil, nil) + trie.cache = self.cache.Copy() + if self.root != nil { + trie.root = self.root.Copy(trie) + } + + return trie } // Legacy support @@ -177,7 +187,7 @@ func (self *Trie) insert(node Node, key []byte, value Node) Node { return NewShortNode(self, key[:matchlength], n) case *FullNode: - cpy := node.Copy().(*FullNode) + cpy := node.Copy(self).(*FullNode) cpy.set(key[0], self.insert(node.branch(key[0]), key[1:], value)) return cpy @@ -244,7 +254,7 @@ func (self *Trie) delete(node Node, key []byte) Node { } case *FullNode: - n := node.Copy().(*FullNode) + n := node.Copy(self).(*FullNode) n.set(key[0], self.delete(n.branch(key[0]), key[1:])) pos := -1 @@ -301,7 +311,7 @@ func (self *Trie) mknode(value *ethutil.Value) Node { } return fnode case 32: - return &HashNode{value.Bytes()} + return &HashNode{value.Bytes(), self} } return &ValueNode{self, value.Bytes()} @@ -331,4 +341,5 @@ func (self *Trie) store(node Node) interface{} { func (self *Trie) PrintRoot() { fmt.Println(self.root) + fmt.Printf("root=%x\n", self.Root()) } diff --git a/trie/valuenode.go b/trie/valuenode.go index 689befb2ad35b9b1901c91c321a1a9ad5d0574e7..8912b1c82bb5bc91ef4e77a4fd4f1602fb03fea3 100644 --- a/trie/valuenode.go +++ b/trie/valuenode.go @@ -1,5 +1,7 @@ package trie +import "github.com/ethereum/go-ethereum/ethutil" + type ValueNode struct { trie *Trie data []byte @@ -8,6 +10,6 @@ type ValueNode struct { func (self *ValueNode) Value() Node { return self } // Best not to call :-) func (self *ValueNode) Val() []byte { return self.data } func (self *ValueNode) Dirty() bool { return true } -func (self *ValueNode) Copy() Node { return &ValueNode{self.trie, self.data} } +func (self *ValueNode) Copy(t *Trie) Node { return &ValueNode{t, ethutil.CopyBytes(self.data)} } func (self *ValueNode) RlpData() interface{} { return self.data } func (self *ValueNode) Hash() interface{} { return self.data }