| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:45:03 +01:00
										 |  |  | package trie | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 	"container/heap" | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2017-04-18 13:25:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-11-25 18:28:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | // Iterator is a key-value trie iterator that traverses a Trie. | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | type Iterator struct { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	nodeIt NodeIterator | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	Key   []byte // Current data key on which the iterator is positioned on | 
					
						
							|  |  |  | 	Value []byte // Current data value on which the iterator is positioned on | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	Err   error | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 22:14:40 +08:00
										 |  |  | // NewIterator creates a new key-value iterator from a node iterator. | 
					
						
							|  |  |  | // Note that the value returned by the iterator is raw. If the content is encoded | 
					
						
							|  |  |  | // (e.g. storage value is RLP-encoded), it's caller's duty to decode it. | 
					
						
							| 
									
										
										
										
											2017-04-18 13:37:10 +02:00
										 |  |  | func NewIterator(it NodeIterator) *Iterator { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	return &Iterator{ | 
					
						
							|  |  |  | 		nodeIt: it, | 
					
						
							| 
									
										
										
										
											2015-03-05 01:42:32 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | // Next moves the iterator forward one key-value entry. | 
					
						
							|  |  |  | func (it *Iterator) Next() bool { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	for it.nodeIt.Next(true) { | 
					
						
							|  |  |  | 		if it.nodeIt.Leaf() { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 			it.Key = it.nodeIt.LeafKey() | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 			it.Value = it.nodeIt.LeafBlob() | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 			return true | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-06 01:19:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 	it.Key = nil | 
					
						
							|  |  |  | 	it.Value = nil | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	it.Err = it.nodeIt.Error() | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 	return false | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | // Prove generates the Merkle proof for the leaf node the iterator is currently | 
					
						
							|  |  |  | // positioned on. | 
					
						
							|  |  |  | func (it *Iterator) Prove() [][]byte { | 
					
						
							|  |  |  | 	return it.nodeIt.LeafProof() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | // NodeIterator is an iterator to traverse the trie pre-order. | 
					
						
							|  |  |  | type NodeIterator interface { | 
					
						
							|  |  |  | 	// Next moves the iterator to the next node. If the parameter is false, any child | 
					
						
							|  |  |  | 	// nodes will be skipped. | 
					
						
							|  |  |  | 	Next(bool) bool | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	// Error returns the error status of the iterator. | 
					
						
							|  |  |  | 	Error() error | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Hash returns the hash of the current node. | 
					
						
							|  |  |  | 	Hash() common.Hash | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	// Parent returns the hash of the parent of the current node. The hash may be the one | 
					
						
							|  |  |  | 	// grandparent if the immediate parent is an internal node with no hash. | 
					
						
							|  |  |  | 	Parent() common.Hash | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	// Path returns the hex-encoded path to the current node. | 
					
						
							|  |  |  | 	// Callers must not retain references to the return value after calling Next. | 
					
						
							|  |  |  | 	// For leaf nodes, the last element of the path is the 'terminator symbol' 0x10. | 
					
						
							|  |  |  | 	Path() []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Leaf returns true iff the current node is a leaf node. | 
					
						
							|  |  |  | 	Leaf() bool | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// LeafKey returns the key of the leaf. The method panics if the iterator is not | 
					
						
							|  |  |  | 	// positioned at a leaf. Callers must not retain references to the value after | 
					
						
							|  |  |  | 	// calling Next. | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	LeafKey() []byte | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// LeafBlob returns the content of the leaf. The method panics if the iterator | 
					
						
							|  |  |  | 	// is not positioned at a leaf. Callers must not retain references to the value | 
					
						
							|  |  |  | 	// after calling Next. | 
					
						
							|  |  |  | 	LeafBlob() []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// LeafProof returns the Merkle proof of the leaf. The method panics if the | 
					
						
							|  |  |  | 	// iterator is not positioned at a leaf. Callers must not retain references | 
					
						
							|  |  |  | 	// to the value after calling Next. | 
					
						
							|  |  |  | 	LeafProof() [][]byte | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // nodeIteratorState represents the iteration state at one particular node of the | 
					
						
							|  |  |  | // trie, which can be resumed at a later invocation. | 
					
						
							|  |  |  | type nodeIteratorState struct { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	hash    common.Hash // Hash of the node being iterated (nil if not standalone) | 
					
						
							|  |  |  | 	node    node        // Trie node being iterated | 
					
						
							|  |  |  | 	parent  common.Hash // Hash of the first full ancestor node (nil if current is the root) | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	index   int         // Child to be processed next | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	pathlen int         // Length of the path to this node | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | type nodeIterator struct { | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	trie  *Trie                // Trie being iterated | 
					
						
							|  |  |  | 	stack []*nodeIteratorState // Hierarchy of trie nodes persisting the iteration state | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	path  []byte               // Path to the current node | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	err   error                // Failure set in case of an internal error in the iterator | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-21 13:41:31 -07:00
										 |  |  | // errIteratorEnd is stored in nodeIterator.err when iteration is done. | 
					
						
							|  |  |  | var errIteratorEnd = errors.New("end of iteration") | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // seekError is stored in nodeIterator.err if the initial seek has failed. | 
					
						
							|  |  |  | type seekError struct { | 
					
						
							|  |  |  | 	key []byte | 
					
						
							|  |  |  | 	err error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e seekError) Error() string { | 
					
						
							|  |  |  | 	return "seek error: " + e.err.Error() | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | func newNodeIterator(trie *Trie, start []byte) NodeIterator { | 
					
						
							| 
									
										
										
										
											2016-05-19 13:24:14 +03:00
										 |  |  | 	if trie.Hash() == emptyState { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 		return new(nodeIterator) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	it := &nodeIterator{trie: trie} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	it.err = it.seek(start) | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	return it | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) Hash() common.Hash { | 
					
						
							|  |  |  | 	if len(it.stack) == 0 { | 
					
						
							|  |  |  | 		return common.Hash{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return it.stack[len(it.stack)-1].hash | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) Parent() common.Hash { | 
					
						
							|  |  |  | 	if len(it.stack) == 0 { | 
					
						
							|  |  |  | 		return common.Hash{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return it.stack[len(it.stack)-1].parent | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) Leaf() bool { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	return hasTerm(it.path) | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *nodeIterator) LeafKey() []byte { | 
					
						
							|  |  |  | 	if len(it.stack) > 0 { | 
					
						
							|  |  |  | 		if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { | 
					
						
							|  |  |  | 			return hexToKeybytes(it.path) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	panic("not at leaf") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | func (it *nodeIterator) LeafBlob() []byte { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if len(it.stack) > 0 { | 
					
						
							|  |  |  | 		if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { | 
					
						
							|  |  |  | 			return []byte(node) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	panic("not at leaf") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *nodeIterator) LeafProof() [][]byte { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if len(it.stack) > 0 { | 
					
						
							|  |  |  | 		if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { | 
					
						
							| 
									
										
										
										
											2020-02-04 13:02:38 +01:00
										 |  |  | 			hasher := newHasher(false) | 
					
						
							| 
									
										
										
										
											2018-11-16 10:50:48 +01:00
										 |  |  | 			defer returnHasherToPool(hasher) | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 			proofs := make([][]byte, 0, len(it.stack)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for i, item := range it.stack[:len(it.stack)-1] { | 
					
						
							|  |  |  | 				// Gather nodes that end up as hash nodes (or the root) | 
					
						
							| 
									
										
										
										
											2020-02-03 16:28:30 +01:00
										 |  |  | 				node, hashed := hasher.proofHash(item.node) | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | 				if _, ok := hashed.(hashNode); ok || i == 0 { | 
					
						
							|  |  |  | 					enc, _ := rlp.EncodeToBytes(node) | 
					
						
							|  |  |  | 					proofs = append(proofs, enc) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return proofs | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	panic("not at leaf") | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) Path() []byte { | 
					
						
							|  |  |  | 	return it.path | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) Error() error { | 
					
						
							| 
									
										
										
										
											2018-05-21 13:41:31 -07:00
										 |  |  | 	if it.err == errIteratorEnd { | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if seek, ok := it.err.(seekError); ok { | 
					
						
							|  |  |  | 		return seek.err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	return it.err | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Next moves the iterator to the next node, returning whether there are any | 
					
						
							| 
									
										
										
										
											2016-02-16 12:37:00 +02:00
										 |  |  | // further nodes. In case of an internal error this method returns false and | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | // sets the Error field to the encountered failure. If `descend` is false, | 
					
						
							|  |  |  | // skips iterating over any subnodes of the current node. | 
					
						
							|  |  |  | func (it *nodeIterator) Next(descend bool) bool { | 
					
						
							| 
									
										
										
										
											2018-05-21 13:41:31 -07:00
										 |  |  | 	if it.err == errIteratorEnd { | 
					
						
							| 
									
										
										
										
											2016-02-16 12:37:00 +02:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if seek, ok := it.err.(seekError); ok { | 
					
						
							|  |  |  | 		if it.err = it.seek(seek.key); it.err != nil { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Otherwise step forward with the iterator and report any errors. | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	state, parentIndex, path, err := it.peek(descend) | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	it.err = err | 
					
						
							|  |  |  | 	if it.err != nil { | 
					
						
							| 
									
										
										
										
											2016-02-16 12:37:00 +02:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	it.push(state, parentIndex, path) | 
					
						
							|  |  |  | 	return true | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | func (it *nodeIterator) seek(prefix []byte) error { | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	// The path we're looking for is the hex encoded key without terminator. | 
					
						
							|  |  |  | 	key := keybytesToHex(prefix) | 
					
						
							|  |  |  | 	key = key[:len(key)-1] | 
					
						
							|  |  |  | 	// Move forward until we're just before the closest match to key. | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		state, parentIndex, path, err := it.peek(bytes.HasPrefix(key, it.path)) | 
					
						
							| 
									
										
										
										
											2018-05-21 13:41:31 -07:00
										 |  |  | 		if err == errIteratorEnd { | 
					
						
							|  |  |  | 			return errIteratorEnd | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 		} else if err != nil { | 
					
						
							|  |  |  | 			return seekError{prefix, err} | 
					
						
							|  |  |  | 		} else if bytes.Compare(path, key) >= 0 { | 
					
						
							|  |  |  | 			return nil | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		it.push(state, parentIndex, path) | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // peek creates the next state of the iterator. | 
					
						
							|  |  |  | func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, error) { | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	if len(it.stack) == 0 { | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 		// Initialize the iterator if we've just started. | 
					
						
							| 
									
										
										
										
											2016-05-19 13:24:14 +03:00
										 |  |  | 		root := it.trie.Hash() | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 		state := &nodeIteratorState{node: it.trie.root, index: -1} | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 		if root != emptyRoot { | 
					
						
							|  |  |  | 			state.hash = root | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 		err := state.resolve(it.trie, nil) | 
					
						
							|  |  |  | 		return state, nil, nil, err | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if !descend { | 
					
						
							|  |  |  | 		// If we're skipping children, pop the current node first | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 		it.pop() | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	// Continue iteration to the next child | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	for len(it.stack) > 0 { | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 		parent := it.stack[len(it.stack)-1] | 
					
						
							| 
									
										
										
										
											2016-01-08 13:46:45 +02:00
										 |  |  | 		ancestor := parent.hash | 
					
						
							|  |  |  | 		if (ancestor == common.Hash{}) { | 
					
						
							|  |  |  | 			ancestor = parent.parent | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 		state, path, ok := it.nextChild(parent, ancestor) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			if err := state.resolve(it.trie, path); err != nil { | 
					
						
							|  |  |  | 				return parent, &parent.index, path, err | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 			return state, &parent.index, path, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// No more child nodes, move back up. | 
					
						
							|  |  |  | 		it.pop() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-21 13:41:31 -07:00
										 |  |  | 	return nil, nil, nil, errIteratorEnd | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (st *nodeIteratorState) resolve(tr *Trie, path []byte) error { | 
					
						
							|  |  |  | 	if hash, ok := st.node.(hashNode); ok { | 
					
						
							|  |  |  | 		resolved, err := tr.resolveHash(hash, path) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		st.node = resolved | 
					
						
							|  |  |  | 		st.hash = common.BytesToHash(hash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Hash) (*nodeIteratorState, []byte, bool) { | 
					
						
							|  |  |  | 	switch node := parent.node.(type) { | 
					
						
							|  |  |  | 	case *fullNode: | 
					
						
							|  |  |  | 		// Full node, move to the first non-nil child. | 
					
						
							|  |  |  | 		for i := parent.index + 1; i < len(node.Children); i++ { | 
					
						
							|  |  |  | 			child := node.Children[i] | 
					
						
							|  |  |  | 			if child != nil { | 
					
						
							|  |  |  | 				hash, _ := child.cache() | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 				state := &nodeIteratorState{ | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 					hash:    common.BytesToHash(hash), | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 					node:    child, | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 					parent:  ancestor, | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 					index:   -1, | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 					pathlen: len(it.path), | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 				path := append(it.path, byte(i)) | 
					
						
							|  |  |  | 				parent.index = i - 1 | 
					
						
							|  |  |  | 				return state, path, true | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	case *shortNode: | 
					
						
							|  |  |  | 		// Short node, return the pointer singleton child | 
					
						
							|  |  |  | 		if parent.index < 0 { | 
					
						
							|  |  |  | 			hash, _ := node.Val.cache() | 
					
						
							|  |  |  | 			state := &nodeIteratorState{ | 
					
						
							|  |  |  | 				hash:    common.BytesToHash(hash), | 
					
						
							|  |  |  | 				node:    node.Val, | 
					
						
							|  |  |  | 				parent:  ancestor, | 
					
						
							|  |  |  | 				index:   -1, | 
					
						
							|  |  |  | 				pathlen: len(it.path), | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 			path := append(it.path, node.Key...) | 
					
						
							|  |  |  | 			return state, path, true | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	return parent, it.path, false | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []byte) { | 
					
						
							|  |  |  | 	it.path = path | 
					
						
							|  |  |  | 	it.stack = append(it.stack, state) | 
					
						
							|  |  |  | 	if parentIndex != nil { | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 		*parentIndex++ | 
					
						
							| 
									
										
										
										
											2017-04-13 14:41:24 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *nodeIterator) pop() { | 
					
						
							|  |  |  | 	parent := it.stack[len(it.stack)-1] | 
					
						
							|  |  |  | 	it.path = it.path[:parent.pathlen] | 
					
						
							|  |  |  | 	it.stack = it.stack[:len(it.stack)-1] | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | func compareNodes(a, b NodeIterator) int { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if cmp := bytes.Compare(a.Path(), b.Path()); cmp != 0 { | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 		return cmp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if a.Leaf() && !b.Leaf() { | 
					
						
							|  |  |  | 		return -1 | 
					
						
							|  |  |  | 	} else if b.Leaf() && !a.Leaf() { | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if cmp := bytes.Compare(a.Hash().Bytes(), b.Hash().Bytes()); cmp != 0 { | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 		return cmp | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	if a.Leaf() && b.Leaf() { | 
					
						
							|  |  |  | 		return bytes.Compare(a.LeafBlob(), b.LeafBlob()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0 | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | type differenceIterator struct { | 
					
						
							|  |  |  | 	a, b  NodeIterator // Nodes returned are those in b - a. | 
					
						
							|  |  |  | 	eof   bool         // Indicates a has run out of elements | 
					
						
							|  |  |  | 	count int          // Number of nodes scanned on either trie | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | // NewDifferenceIterator constructs a NodeIterator that iterates over elements in b that | 
					
						
							|  |  |  | // are not in a. Returns the iterator, and a pointer to an integer recording the number | 
					
						
							|  |  |  | // of nodes seen. | 
					
						
							|  |  |  | func NewDifferenceIterator(a, b NodeIterator) (NodeIterator, *int) { | 
					
						
							|  |  |  | 	a.Next(true) | 
					
						
							|  |  |  | 	it := &differenceIterator{ | 
					
						
							|  |  |  | 		a: a, | 
					
						
							|  |  |  | 		b: b, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return it, &it.count | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *differenceIterator) Hash() common.Hash { | 
					
						
							|  |  |  | 	return it.b.Hash() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *differenceIterator) Parent() common.Hash { | 
					
						
							|  |  |  | 	return it.b.Parent() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *differenceIterator) Leaf() bool { | 
					
						
							|  |  |  | 	return it.b.Leaf() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *differenceIterator) LeafKey() []byte { | 
					
						
							|  |  |  | 	return it.b.LeafKey() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | func (it *differenceIterator) LeafBlob() []byte { | 
					
						
							|  |  |  | 	return it.b.LeafBlob() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *differenceIterator) LeafProof() [][]byte { | 
					
						
							|  |  |  | 	return it.b.LeafProof() | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | func (it *differenceIterator) Path() []byte { | 
					
						
							|  |  |  | 	return it.b.Path() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *differenceIterator) Next(bool) bool { | 
					
						
							|  |  |  | 	// Invariants: | 
					
						
							|  |  |  | 	// - We always advance at least one element in b. | 
					
						
							|  |  |  | 	// - At the start of this function, a's path is lexically greater than b's. | 
					
						
							|  |  |  | 	if !it.b.Next(true) { | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 	it.count++ | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if it.eof { | 
					
						
							|  |  |  | 		// a has reached eof, so we just return all elements from b | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 		switch compareNodes(it.a, it.b) { | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 		case -1: | 
					
						
							|  |  |  | 			// b jumped past a; advance a | 
					
						
							|  |  |  | 			if !it.a.Next(true) { | 
					
						
							|  |  |  | 				it.eof = true | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 			it.count++ | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 		case 1: | 
					
						
							|  |  |  | 			// b is before a | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		case 0: | 
					
						
							|  |  |  | 			// a and b are identical; skip this whole subtree if the nodes have hashes | 
					
						
							|  |  |  | 			hasHash := it.a.Hash() == common.Hash{} | 
					
						
							|  |  |  | 			if !it.b.Next(hasHash) { | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 			it.count++ | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 			if !it.a.Next(hasHash) { | 
					
						
							|  |  |  | 				it.eof = true | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 			it.count++ | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-06 12:11:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | func (it *differenceIterator) Error() error { | 
					
						
							|  |  |  | 	if err := it.a.Error(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-22 22:49:34 +00:00
										 |  |  | 	return it.b.Error() | 
					
						
							| 
									
										
										
										
											2015-12-28 15:20:37 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | type nodeIteratorHeap []NodeIterator | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (h nodeIteratorHeap) Len() int            { return len(h) } | 
					
						
							|  |  |  | func (h nodeIteratorHeap) Less(i, j int) bool  { return compareNodes(h[i], h[j]) < 0 } | 
					
						
							|  |  |  | func (h nodeIteratorHeap) Swap(i, j int)       { h[i], h[j] = h[j], h[i] } | 
					
						
							|  |  |  | func (h *nodeIteratorHeap) Push(x interface{}) { *h = append(*h, x.(NodeIterator)) } | 
					
						
							|  |  |  | func (h *nodeIteratorHeap) Pop() interface{} { | 
					
						
							|  |  |  | 	n := len(*h) | 
					
						
							|  |  |  | 	x := (*h)[n-1] | 
					
						
							|  |  |  | 	*h = (*h)[0 : n-1] | 
					
						
							|  |  |  | 	return x | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type unionIterator struct { | 
					
						
							|  |  |  | 	items *nodeIteratorHeap // Nodes returned are the union of the ones in these iterators | 
					
						
							|  |  |  | 	count int               // Number of nodes scanned across all tries | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewUnionIterator constructs a NodeIterator that iterates over elements in the union | 
					
						
							|  |  |  | // of the provided NodeIterators. Returns the iterator, and a pointer to an integer | 
					
						
							|  |  |  | // recording the number of nodes visited. | 
					
						
							|  |  |  | func NewUnionIterator(iters []NodeIterator) (NodeIterator, *int) { | 
					
						
							|  |  |  | 	h := make(nodeIteratorHeap, len(iters)) | 
					
						
							|  |  |  | 	copy(h, iters) | 
					
						
							|  |  |  | 	heap.Init(&h) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | 	ui := &unionIterator{items: &h} | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 	return ui, &ui.count | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *unionIterator) Hash() common.Hash { | 
					
						
							|  |  |  | 	return (*it.items)[0].Hash() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *unionIterator) Parent() common.Hash { | 
					
						
							|  |  |  | 	return (*it.items)[0].Parent() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *unionIterator) Leaf() bool { | 
					
						
							|  |  |  | 	return (*it.items)[0].Leaf() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *unionIterator) LeafKey() []byte { | 
					
						
							|  |  |  | 	return (*it.items)[0].LeafKey() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | func (it *unionIterator) LeafBlob() []byte { | 
					
						
							|  |  |  | 	return (*it.items)[0].LeafBlob() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 12:49:27 +03:00
										 |  |  | func (it *unionIterator) LeafProof() [][]byte { | 
					
						
							|  |  |  | 	return (*it.items)[0].LeafProof() | 
					
						
							| 
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | func (it *unionIterator) Path() []byte { | 
					
						
							|  |  |  | 	return (*it.items)[0].Path() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Next returns the next node in the union of tries being iterated over. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // It does this by maintaining a heap of iterators, sorted by the iteration | 
					
						
							|  |  |  | // order of their next elements, with one entry for each source trie. Each | 
					
						
							|  |  |  | // time Next() is called, it takes the least element from the heap to return, | 
					
						
							|  |  |  | // advancing any other iterators that also point to that same element. These | 
					
						
							|  |  |  | // iterators are called with descend=false, since we know that any nodes under | 
					
						
							|  |  |  | // these nodes will also be duplicates, found in the currently selected iterator. | 
					
						
							|  |  |  | // Whenever an iterator is advanced, it is pushed back into the heap if it still | 
					
						
							|  |  |  | // has elements remaining. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // In the case that descend=false - eg, we're asked to ignore all subnodes of the | 
					
						
							|  |  |  | // current node - we also advance any iterators in the heap that have the current | 
					
						
							|  |  |  | // path as a prefix. | 
					
						
							|  |  |  | func (it *unionIterator) Next(descend bool) bool { | 
					
						
							|  |  |  | 	if len(*it.items) == 0 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get the next key from the union | 
					
						
							|  |  |  | 	least := heap.Pop(it.items).(NodeIterator) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Skip over other nodes as long as they're identical, or, if we're not descending, as | 
					
						
							|  |  |  | 	// long as they have the same prefix as the current node. | 
					
						
							|  |  |  | 	for len(*it.items) > 0 && ((!descend && bytes.HasPrefix((*it.items)[0].Path(), least.Path())) || compareNodes(least, (*it.items)[0]) == 0) { | 
					
						
							|  |  |  | 		skipped := heap.Pop(it.items).(NodeIterator) | 
					
						
							|  |  |  | 		// Skip the whole subtree if the nodes have hashes; otherwise just skip this node | 
					
						
							|  |  |  | 		if skipped.Next(skipped.Hash() == common.Hash{}) { | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 			it.count++ | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 			// If there are more elements, push the iterator back on the heap | 
					
						
							|  |  |  | 			heap.Push(it.items, skipped) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if least.Next(descend) { | 
					
						
							| 
									
										
										
										
											2018-05-02 01:24:34 -07:00
										 |  |  | 		it.count++ | 
					
						
							| 
									
										
										
										
											2017-04-13 10:14:19 +01:00
										 |  |  | 		heap.Push(it.items, least) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return len(*it.items) > 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (it *unionIterator) Error() error { | 
					
						
							|  |  |  | 	for i := 0; i < len(*it.items); i++ { | 
					
						
							|  |  |  | 		if err := (*it.items)[i].Error(); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |