| 
									
										
										
										
											2014-10-31 14:45:03 +01:00
										 |  |  | package trie | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-07-02 17:47:18 +02:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	"container/list" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2014-05-21 01:12:28 +02:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2014-08-04 10:38:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 12:37:43 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2014-10-23 15:01:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) { | 
					
						
							|  |  |  | 	t2 := New(nil, backend) | 
					
						
							| 
									
										
										
										
											2014-07-02 17:47:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	it := t1.Iterator() | 
					
						
							|  |  |  | 	for it.Next() { | 
					
						
							|  |  |  | 		t2.Update(it.Key, it.Value) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return bytes.Equal(t2.Hash(), t1.Hash()), t2 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | type Trie struct { | 
					
						
							|  |  |  | 	mu       sync.Mutex | 
					
						
							|  |  |  | 	root     Node | 
					
						
							|  |  |  | 	roothash []byte | 
					
						
							|  |  |  | 	cache    *Cache | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	revisions *list.List | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func New(root []byte, backend Backend) *Trie { | 
					
						
							|  |  |  | 	trie := &Trie{} | 
					
						
							|  |  |  | 	trie.revisions = list.New() | 
					
						
							|  |  |  | 	trie.roothash = root | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 	if backend != nil { | 
					
						
							|  |  |  | 		trie.cache = NewCache(backend) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if root != nil { | 
					
						
							|  |  |  | 		value := ethutil.NewValueFromBytes(trie.cache.Get(root)) | 
					
						
							|  |  |  | 		trie.root = trie.mknode(value) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return trie | 
					
						
							| 
									
										
										
										
											2014-06-30 13:08:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) Iterator() *Iterator { | 
					
						
							|  |  |  | 	return NewIterator(self) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) Copy() *Trie { | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | // Legacy support | 
					
						
							|  |  |  | 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 && len(byts) > 0 { | 
					
						
							|  |  |  | 			hash = byts | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			hash = crypto.Sha3(ethutil.Encode(self.root.RlpData())) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		hash = crypto.Sha3(ethutil.Encode("")) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if !bytes.Equal(hash, self.roothash) { | 
					
						
							|  |  |  | 		self.revisions.PushBack(self.roothash) | 
					
						
							|  |  |  | 		self.roothash = hash | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return hash | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) Commit() { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	// Hash first | 
					
						
							|  |  |  | 	self.Hash() | 
					
						
							| 
									
										
										
										
											2014-04-29 12:36:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	self.cache.Flush() | 
					
						
							| 
									
										
										
										
											2014-04-29 12:36:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | // Reset should only be called if the trie has been hashed | 
					
						
							|  |  |  | func (self *Trie) Reset() { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-04-29 12:36:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	self.cache.Reset() | 
					
						
							| 
									
										
										
										
											2014-10-29 14:20:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if self.revisions.Len() > 0 { | 
					
						
							|  |  |  | 		revision := self.revisions.Remove(self.revisions.Back()).([]byte) | 
					
						
							|  |  |  | 		self.roothash = revision | 
					
						
							| 
									
										
										
										
											2014-10-29 14:20:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	value := ethutil.NewValueFromBytes(self.cache.Get(self.roothash)) | 
					
						
							|  |  |  | 	self.root = self.mknode(value) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) UpdateString(key, value string) Node { return self.Update([]byte(key), []byte(value)) } | 
					
						
							|  |  |  | func (self *Trie) Update(key, value []byte) Node { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-05-21 01:12:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	k := CompactHexDecode(string(key)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if len(value) != 0 { | 
					
						
							|  |  |  | 		self.root = self.insert(self.root, k, &ValueNode{self, value}) | 
					
						
							| 
									
										
										
										
											2014-11-18 12:03:09 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		self.root = self.delete(self.root, k) | 
					
						
							| 
									
										
										
										
											2014-11-18 12:03:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return self.root | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) GetString(key string) []byte { return self.Get([]byte(key)) } | 
					
						
							|  |  |  | func (self *Trie) Get(key []byte) []byte { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	k := CompactHexDecode(string(key)) | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	n := self.get(self.root, k) | 
					
						
							|  |  |  | 	if n != nil { | 
					
						
							|  |  |  | 		return n.(*ValueNode).Val() | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) DeleteString(key string) Node { return self.Delete([]byte(key)) } | 
					
						
							|  |  |  | func (self *Trie) Delete(key []byte) Node { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	k := CompactHexDecode(string(key)) | 
					
						
							|  |  |  | 	self.root = self.delete(self.root, k) | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return self.root | 
					
						
							| 
									
										
										
										
											2014-07-02 13:40:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) insert(node Node, key []byte, value Node) Node { | 
					
						
							|  |  |  | 	if len(key) == 0 { | 
					
						
							|  |  |  | 		return value | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if node == nil { | 
					
						
							|  |  |  | 		return NewShortNode(self, key, value) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	switch node := node.(type) { | 
					
						
							|  |  |  | 	case *ShortNode: | 
					
						
							|  |  |  | 		k := node.Key() | 
					
						
							|  |  |  | 		cnode := node.Value() | 
					
						
							|  |  |  | 		if bytes.Equal(k, key) { | 
					
						
							|  |  |  | 			return NewShortNode(self, key, value) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		var n Node | 
					
						
							|  |  |  | 		matchlength := MatchingNibbleLength(key, k) | 
					
						
							|  |  |  | 		if matchlength == len(k) { | 
					
						
							|  |  |  | 			n = self.insert(cnode, key[matchlength:], value) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 			pnode := self.insert(nil, k[matchlength+1:], cnode) | 
					
						
							|  |  |  | 			nnode := self.insert(nil, key[matchlength+1:], value) | 
					
						
							|  |  |  | 			fulln := NewFullNode(self) | 
					
						
							|  |  |  | 			fulln.set(k[matchlength], pnode) | 
					
						
							|  |  |  | 			fulln.set(key[matchlength], nnode) | 
					
						
							|  |  |  | 			n = fulln | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if matchlength == 0 { | 
					
						
							|  |  |  | 			return n | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return NewShortNode(self, key[:matchlength], n) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	case *FullNode: | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 		cpy := node.Copy(self).(*FullNode) | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		cpy.set(key[0], self.insert(node.branch(key[0]), key[1:], value)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return cpy | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Sprintf("%T: invalid node: %v", node, node)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) get(node Node, key []byte) Node { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	if len(key) == 0 { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return node | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	if node == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	switch node := node.(type) { | 
					
						
							|  |  |  | 	case *ShortNode: | 
					
						
							|  |  |  | 		k := node.Key() | 
					
						
							|  |  |  | 		cnode := node.Value() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		if len(key) >= len(k) && bytes.Equal(k, key[:len(k)]) { | 
					
						
							|  |  |  | 			return self.get(cnode, key[len(k):]) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	case *FullNode: | 
					
						
							|  |  |  | 		return self.get(node.branch(key[0]), key[1:]) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Sprintf("%T: invalid node: %v", node, node)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) delete(node Node, key []byte) Node { | 
					
						
							|  |  |  | 	if len(key) == 0 && node == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	switch node := node.(type) { | 
					
						
							|  |  |  | 	case *ShortNode: | 
					
						
							|  |  |  | 		k := node.Key() | 
					
						
							|  |  |  | 		cnode := node.Value() | 
					
						
							|  |  |  | 		if bytes.Equal(key, k) { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} else if bytes.Equal(key[:len(k)], k) { | 
					
						
							|  |  |  | 			child := self.delete(cnode, key[len(k):]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var n Node | 
					
						
							|  |  |  | 			switch child := child.(type) { | 
					
						
							|  |  |  | 			case *ShortNode: | 
					
						
							|  |  |  | 				nkey := append(k, child.Key()...) | 
					
						
							|  |  |  | 				n = NewShortNode(self, nkey, child.Value()) | 
					
						
							|  |  |  | 			case *FullNode: | 
					
						
							|  |  |  | 				sn := NewShortNode(self, node.Key(), child) | 
					
						
							|  |  |  | 				sn.key = node.key | 
					
						
							|  |  |  | 				n = sn | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 			return n | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			return node | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	case *FullNode: | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 		n := node.Copy(self).(*FullNode) | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		n.set(key[0], self.delete(n.branch(key[0]), key[1:])) | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		pos := -1 | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 		for i := 0; i < 17; i++ { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 			if n.branch(byte(i)) != nil { | 
					
						
							|  |  |  | 				if pos == -1 { | 
					
						
							|  |  |  | 					pos = i | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 					pos = -2 | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		var nnode Node | 
					
						
							|  |  |  | 		if pos == 16 { | 
					
						
							|  |  |  | 			nnode = NewShortNode(self, []byte{16}, n.branch(byte(pos))) | 
					
						
							|  |  |  | 		} else if pos >= 0 { | 
					
						
							|  |  |  | 			cnode := n.branch(byte(pos)) | 
					
						
							|  |  |  | 			switch cnode := cnode.(type) { | 
					
						
							|  |  |  | 			case *ShortNode: | 
					
						
							|  |  |  | 				// Stitch keys | 
					
						
							|  |  |  | 				k := append([]byte{byte(pos)}, cnode.Key()...) | 
					
						
							|  |  |  | 				nnode = NewShortNode(self, k, cnode.Value()) | 
					
						
							|  |  |  | 			case *FullNode: | 
					
						
							|  |  |  | 				nnode = NewShortNode(self, []byte{byte(pos)}, n.branch(byte(pos))) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 			nnode = n | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return nnode | 
					
						
							|  |  |  | 	case nil: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Sprintf("%T: invalid node: %v (%v)", node, node, key)) | 
					
						
							| 
									
										
										
										
											2014-02-20 14:40:00 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | // casting functions and cache storing | 
					
						
							|  |  |  | func (self *Trie) mknode(value *ethutil.Value) Node { | 
					
						
							|  |  |  | 	l := value.Len() | 
					
						
							|  |  |  | 	switch l { | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		// A value node may consists of 2 bytes. | 
					
						
							|  |  |  | 		if value.Get(0).Len() != 0 { | 
					
						
							|  |  |  | 			return NewShortNode(self, CompactDecode(string(value.Get(0).Bytes())), self.mknode(value.Get(1))) | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	case 17: | 
					
						
							|  |  |  | 		fnode := NewFullNode(self) | 
					
						
							|  |  |  | 		for i := 0; i < l; i++ { | 
					
						
							|  |  |  | 			fnode.set(byte(i), self.mknode(value.Get(i))) | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return fnode | 
					
						
							|  |  |  | 	case 32: | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 		return &HashNode{value.Bytes(), self} | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return &ValueNode{self, value.Bytes()} | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) trans(node Node) Node { | 
					
						
							|  |  |  | 	switch node := node.(type) { | 
					
						
							|  |  |  | 	case *HashNode: | 
					
						
							|  |  |  | 		value := ethutil.NewValueFromBytes(self.cache.Get(node.key)) | 
					
						
							|  |  |  | 		return self.mknode(value) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return node | 
					
						
							| 
									
										
										
										
											2014-02-24 12:11:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) store(node Node) interface{} { | 
					
						
							|  |  |  | 	data := ethutil.Encode(node) | 
					
						
							|  |  |  | 	if len(data) >= 32 { | 
					
						
							|  |  |  | 		key := crypto.Sha3(data) | 
					
						
							|  |  |  | 		self.cache.Put(key, data) | 
					
						
							| 
									
										
										
										
											2014-05-27 01:08:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 		return key | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-27 01:08:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | 	return node.RlpData() | 
					
						
							| 
									
										
										
										
											2014-05-27 01:08:51 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:47:04 +01:00
										 |  |  | func (self *Trie) PrintRoot() { | 
					
						
							|  |  |  | 	fmt.Println(self.root) | 
					
						
							| 
									
										
										
										
											2015-02-02 19:58:34 -08:00
										 |  |  | 	fmt.Printf("root=%x\n", self.Root()) | 
					
						
							| 
									
										
										
										
											2014-05-27 01:08:51 +02:00
										 |  |  | } |