github.com/MetalBlockchain/subnet-evm@v0.4.9/trie/iterator.go (about) 1 // (c) 2020-2021, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2014 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package trie 28 29 import ( 30 "bytes" 31 "container/heap" 32 "errors" 33 34 "github.com/MetalBlockchain/subnet-evm/ethdb" 35 "github.com/ethereum/go-ethereum/common" 36 ) 37 38 // Iterator is a key-value trie iterator that traverses a Trie. 39 type Iterator struct { 40 nodeIt NodeIterator 41 42 Key []byte // Current data key on which the iterator is positioned on 43 Value []byte // Current data value on which the iterator is positioned on 44 Err error 45 } 46 47 // NewIterator creates a new key-value iterator from a node iterator. 48 // Note that the value returned by the iterator is raw. If the content is encoded 49 // (e.g. storage value is RLP-encoded), it's caller's duty to decode it. 50 func NewIterator(it NodeIterator) *Iterator { 51 return &Iterator{ 52 nodeIt: it, 53 } 54 } 55 56 // Next moves the iterator forward one key-value entry. 57 func (it *Iterator) Next() bool { 58 for it.nodeIt.Next(true) { 59 if it.nodeIt.Leaf() { 60 it.Key = it.nodeIt.LeafKey() 61 it.Value = it.nodeIt.LeafBlob() 62 return true 63 } 64 } 65 it.Key = nil 66 it.Value = nil 67 it.Err = it.nodeIt.Error() 68 return false 69 } 70 71 // Prove generates the Merkle proof for the leaf node the iterator is currently 72 // positioned on. 73 func (it *Iterator) Prove() [][]byte { 74 return it.nodeIt.LeafProof() 75 } 76 77 // NodeIterator is an iterator to traverse the trie pre-order. 78 type NodeIterator interface { 79 // Next moves the iterator to the next node. If the parameter is false, any child 80 // nodes will be skipped. 81 Next(bool) bool 82 83 // Error returns the error status of the iterator. 84 Error() error 85 86 // Hash returns the hash of the current node. 87 Hash() common.Hash 88 89 // Parent returns the hash of the parent of the current node. The hash may be the one 90 // grandparent if the immediate parent is an internal node with no hash. 91 Parent() common.Hash 92 93 // Path returns the hex-encoded path to the current node. 94 // Callers must not retain references to the return value after calling Next. 95 // For leaf nodes, the last element of the path is the 'terminator symbol' 0x10. 96 Path() []byte 97 98 // NodeBlob returns the rlp-encoded value of the current iterated node. 99 // If the node is an embedded node in its parent, nil is returned then. 100 NodeBlob() []byte 101 102 // Leaf returns true iff the current node is a leaf node. 103 Leaf() bool 104 105 // LeafKey returns the key of the leaf. The method panics if the iterator is not 106 // positioned at a leaf. Callers must not retain references to the value after 107 // calling Next. 108 LeafKey() []byte 109 110 // LeafBlob returns the content of the leaf. The method panics if the iterator 111 // is not positioned at a leaf. Callers must not retain references to the value 112 // after calling Next. 113 LeafBlob() []byte 114 115 // LeafProof returns the Merkle proof of the leaf. The method panics if the 116 // iterator is not positioned at a leaf. Callers must not retain references 117 // to the value after calling Next. 118 LeafProof() [][]byte 119 120 // AddResolver sets an intermediate database to use for looking up trie nodes 121 // before reaching into the real persistent layer. 122 // 123 // This is not required for normal operation, rather is an optimization for 124 // cases where trie nodes can be recovered from some external mechanism without 125 // reading from disk. In those cases, this resolver allows short circuiting 126 // accesses and returning them from memory. 127 // 128 // Before adding a similar mechanism to any other place in Geth, consider 129 // making trie.Database an interface and wrapping at that level. It's a huge 130 // refactor, but it could be worth it if another occurrence arises. 131 AddResolver(ethdb.KeyValueReader) 132 } 133 134 // nodeIteratorState represents the iteration state at one particular node of the 135 // trie, which can be resumed at a later invocation. 136 type nodeIteratorState struct { 137 hash common.Hash // Hash of the node being iterated (nil if not standalone) 138 node node // Trie node being iterated 139 parent common.Hash // Hash of the first full ancestor node (nil if current is the root) 140 index int // Child to be processed next 141 pathlen int // Length of the path to this node 142 } 143 144 type nodeIterator struct { 145 trie *Trie // Trie being iterated 146 stack []*nodeIteratorState // Hierarchy of trie nodes persisting the iteration state 147 path []byte // Path to the current node 148 err error // Failure set in case of an internal error in the iterator 149 150 resolver ethdb.KeyValueReader // Optional intermediate resolver above the disk layer 151 } 152 153 // errIteratorEnd is stored in nodeIterator.err when iteration is done. 154 var errIteratorEnd = errors.New("end of iteration") 155 156 // seekError is stored in nodeIterator.err if the initial seek has failed. 157 type seekError struct { 158 key []byte 159 err error 160 } 161 162 func (e seekError) Error() string { 163 return "seek error: " + e.err.Error() 164 } 165 166 func newNodeIterator(trie *Trie, start []byte) NodeIterator { 167 if trie.Hash() == emptyRoot { 168 return &nodeIterator{ 169 trie: trie, 170 err: errIteratorEnd, 171 } 172 } 173 it := &nodeIterator{trie: trie} 174 it.err = it.seek(start) 175 return it 176 } 177 178 func (it *nodeIterator) AddResolver(resolver ethdb.KeyValueReader) { 179 it.resolver = resolver 180 } 181 182 func (it *nodeIterator) Hash() common.Hash { 183 if len(it.stack) == 0 { 184 return common.Hash{} 185 } 186 return it.stack[len(it.stack)-1].hash 187 } 188 189 func (it *nodeIterator) Parent() common.Hash { 190 if len(it.stack) == 0 { 191 return common.Hash{} 192 } 193 return it.stack[len(it.stack)-1].parent 194 } 195 196 func (it *nodeIterator) Leaf() bool { 197 return hasTerm(it.path) 198 } 199 200 func (it *nodeIterator) LeafKey() []byte { 201 if len(it.stack) > 0 { 202 if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { 203 return hexToKeybytes(it.path) 204 } 205 } 206 panic("not at leaf") 207 } 208 209 func (it *nodeIterator) LeafBlob() []byte { 210 if len(it.stack) > 0 { 211 if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { 212 return node 213 } 214 } 215 panic("not at leaf") 216 } 217 218 func (it *nodeIterator) LeafProof() [][]byte { 219 if len(it.stack) > 0 { 220 if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { 221 hasher := newHasher(false) 222 defer returnHasherToPool(hasher) 223 proofs := make([][]byte, 0, len(it.stack)) 224 225 for i, item := range it.stack[:len(it.stack)-1] { 226 // Gather nodes that end up as hash nodes (or the root) 227 node, hashed := hasher.proofHash(item.node) 228 if _, ok := hashed.(hashNode); ok || i == 0 { 229 proofs = append(proofs, nodeToBytes(node)) 230 } 231 } 232 return proofs 233 } 234 } 235 panic("not at leaf") 236 } 237 238 func (it *nodeIterator) Path() []byte { 239 return it.path 240 } 241 242 func (it *nodeIterator) NodeBlob() []byte { 243 if it.Hash() == (common.Hash{}) { 244 return nil // skip the non-standalone node 245 } 246 blob, err := it.resolveBlob(it.Hash().Bytes(), it.Path()) 247 if err != nil { 248 it.err = err 249 return nil 250 } 251 return blob 252 } 253 254 func (it *nodeIterator) Error() error { 255 if it.err == errIteratorEnd { 256 return nil 257 } 258 if seek, ok := it.err.(seekError); ok { 259 return seek.err 260 } 261 return it.err 262 } 263 264 // Next moves the iterator to the next node, returning whether there are any 265 // further nodes. In case of an internal error this method returns false and 266 // sets the Error field to the encountered failure. If `descend` is false, 267 // skips iterating over any subnodes of the current node. 268 func (it *nodeIterator) Next(descend bool) bool { 269 if it.err == errIteratorEnd { 270 return false 271 } 272 if seek, ok := it.err.(seekError); ok { 273 if it.err = it.seek(seek.key); it.err != nil { 274 return false 275 } 276 } 277 // Otherwise step forward with the iterator and report any errors. 278 state, parentIndex, path, err := it.peek(descend) 279 it.err = err 280 if it.err != nil { 281 return false 282 } 283 it.push(state, parentIndex, path) 284 return true 285 } 286 287 func (it *nodeIterator) seek(prefix []byte) error { 288 // The path we're looking for is the hex encoded key without terminator. 289 key := keybytesToHex(prefix) 290 key = key[:len(key)-1] 291 // Move forward until we're just before the closest match to key. 292 for { 293 state, parentIndex, path, err := it.peekSeek(key) 294 if err == errIteratorEnd { 295 return errIteratorEnd 296 } else if err != nil { 297 return seekError{prefix, err} 298 } else if bytes.Compare(path, key) >= 0 { 299 return nil 300 } 301 it.push(state, parentIndex, path) 302 } 303 } 304 305 // init initializes the iterator. 306 func (it *nodeIterator) init() (*nodeIteratorState, error) { 307 root := it.trie.Hash() 308 state := &nodeIteratorState{node: it.trie.root, index: -1} 309 if root != emptyRoot { 310 state.hash = root 311 } 312 return state, state.resolve(it, nil) 313 } 314 315 // peek creates the next state of the iterator. 316 func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, error) { 317 // Initialize the iterator if we've just started. 318 if len(it.stack) == 0 { 319 state, err := it.init() 320 return state, nil, nil, err 321 } 322 if !descend { 323 // If we're skipping children, pop the current node first 324 it.pop() 325 } 326 327 // Continue iteration to the next child 328 for len(it.stack) > 0 { 329 parent := it.stack[len(it.stack)-1] 330 ancestor := parent.hash 331 if (ancestor == common.Hash{}) { 332 ancestor = parent.parent 333 } 334 state, path, ok := it.nextChild(parent, ancestor) 335 if ok { 336 if err := state.resolve(it, path); err != nil { 337 return parent, &parent.index, path, err 338 } 339 return state, &parent.index, path, nil 340 } 341 // No more child nodes, move back up. 342 it.pop() 343 } 344 return nil, nil, nil, errIteratorEnd 345 } 346 347 // peekSeek is like peek, but it also tries to skip resolving hashes by skipping 348 // over the siblings that do not lead towards the desired seek position. 349 func (it *nodeIterator) peekSeek(seekKey []byte) (*nodeIteratorState, *int, []byte, error) { 350 // Initialize the iterator if we've just started. 351 if len(it.stack) == 0 { 352 state, err := it.init() 353 return state, nil, nil, err 354 } 355 if !bytes.HasPrefix(seekKey, it.path) { 356 // If we're skipping children, pop the current node first 357 it.pop() 358 } 359 360 // Continue iteration to the next child 361 for len(it.stack) > 0 { 362 parent := it.stack[len(it.stack)-1] 363 ancestor := parent.hash 364 if (ancestor == common.Hash{}) { 365 ancestor = parent.parent 366 } 367 state, path, ok := it.nextChildAt(parent, ancestor, seekKey) 368 if ok { 369 if err := state.resolve(it, path); err != nil { 370 return parent, &parent.index, path, err 371 } 372 return state, &parent.index, path, nil 373 } 374 // No more child nodes, move back up. 375 it.pop() 376 } 377 return nil, nil, nil, errIteratorEnd 378 } 379 380 func (it *nodeIterator) resolveHash(hash hashNode, path []byte) (node, error) { 381 if it.resolver != nil { 382 if blob, err := it.resolver.Get(hash); err == nil && len(blob) > 0 { 383 if resolved, err := decodeNode(hash, blob); err == nil { 384 return resolved, nil 385 } 386 } 387 } 388 return it.trie.resolveHash(hash, path) 389 } 390 391 func (it *nodeIterator) resolveBlob(hash hashNode, path []byte) ([]byte, error) { 392 if it.resolver != nil { 393 if blob, err := it.resolver.Get(hash); err == nil && len(blob) > 0 { 394 return blob, nil 395 } 396 } 397 return it.trie.resolveBlob(hash, path) 398 } 399 400 func (st *nodeIteratorState) resolve(it *nodeIterator, path []byte) error { 401 if hash, ok := st.node.(hashNode); ok { 402 resolved, err := it.resolveHash(hash, path) 403 if err != nil { 404 return err 405 } 406 st.node = resolved 407 st.hash = common.BytesToHash(hash) 408 } 409 return nil 410 } 411 412 func findChild(n *fullNode, index int, path []byte, ancestor common.Hash) (node, *nodeIteratorState, []byte, int) { 413 var ( 414 child node 415 state *nodeIteratorState 416 childPath []byte 417 ) 418 for ; index < len(n.Children); index++ { 419 if n.Children[index] != nil { 420 child = n.Children[index] 421 hash, _ := child.cache() 422 state = &nodeIteratorState{ 423 hash: common.BytesToHash(hash), 424 node: child, 425 parent: ancestor, 426 index: -1, 427 pathlen: len(path), 428 } 429 childPath = append(childPath, path...) 430 childPath = append(childPath, byte(index)) 431 return child, state, childPath, index 432 } 433 } 434 return nil, nil, nil, 0 435 } 436 437 func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Hash) (*nodeIteratorState, []byte, bool) { 438 switch node := parent.node.(type) { 439 case *fullNode: 440 // Full node, move to the first non-nil child. 441 if child, state, path, index := findChild(node, parent.index+1, it.path, ancestor); child != nil { 442 parent.index = index - 1 443 return state, path, true 444 } 445 case *shortNode: 446 // Short node, return the pointer singleton child 447 if parent.index < 0 { 448 hash, _ := node.Val.cache() 449 state := &nodeIteratorState{ 450 hash: common.BytesToHash(hash), 451 node: node.Val, 452 parent: ancestor, 453 index: -1, 454 pathlen: len(it.path), 455 } 456 path := append(it.path, node.Key...) 457 return state, path, true 458 } 459 } 460 return parent, it.path, false 461 } 462 463 // nextChildAt is similar to nextChild, except that it targets a child as close to the 464 // target key as possible, thus skipping siblings. 465 func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.Hash, key []byte) (*nodeIteratorState, []byte, bool) { 466 switch n := parent.node.(type) { 467 case *fullNode: 468 // Full node, move to the first non-nil child before the desired key position 469 child, state, path, index := findChild(n, parent.index+1, it.path, ancestor) 470 if child == nil { 471 // No more children in this fullnode 472 return parent, it.path, false 473 } 474 // If the child we found is already past the seek position, just return it. 475 if bytes.Compare(path, key) >= 0 { 476 parent.index = index - 1 477 return state, path, true 478 } 479 // The child is before the seek position. Try advancing 480 for { 481 nextChild, nextState, nextPath, nextIndex := findChild(n, index+1, it.path, ancestor) 482 // If we run out of children, or skipped past the target, return the 483 // previous one 484 if nextChild == nil || bytes.Compare(nextPath, key) >= 0 { 485 parent.index = index - 1 486 return state, path, true 487 } 488 // We found a better child closer to the target 489 state, path, index = nextState, nextPath, nextIndex 490 } 491 case *shortNode: 492 // Short node, return the pointer singleton child 493 if parent.index < 0 { 494 hash, _ := n.Val.cache() 495 state := &nodeIteratorState{ 496 hash: common.BytesToHash(hash), 497 node: n.Val, 498 parent: ancestor, 499 index: -1, 500 pathlen: len(it.path), 501 } 502 path := append(it.path, n.Key...) 503 return state, path, true 504 } 505 } 506 return parent, it.path, false 507 } 508 509 func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []byte) { 510 it.path = path 511 it.stack = append(it.stack, state) 512 if parentIndex != nil { 513 *parentIndex++ 514 } 515 } 516 517 func (it *nodeIterator) pop() { 518 last := it.stack[len(it.stack)-1] 519 it.path = it.path[:last.pathlen] 520 it.stack[len(it.stack)-1] = nil 521 it.stack = it.stack[:len(it.stack)-1] 522 } 523 524 func compareNodes(a, b NodeIterator) int { 525 if cmp := bytes.Compare(a.Path(), b.Path()); cmp != 0 { 526 return cmp 527 } 528 if a.Leaf() && !b.Leaf() { 529 return -1 530 } else if b.Leaf() && !a.Leaf() { 531 return 1 532 } 533 if cmp := bytes.Compare(a.Hash().Bytes(), b.Hash().Bytes()); cmp != 0 { 534 return cmp 535 } 536 if a.Leaf() && b.Leaf() { 537 return bytes.Compare(a.LeafBlob(), b.LeafBlob()) 538 } 539 return 0 540 } 541 542 type differenceIterator struct { 543 a, b NodeIterator // Nodes returned are those in b - a. 544 eof bool // Indicates a has run out of elements 545 count int // Number of nodes scanned on either trie 546 } 547 548 // NewDifferenceIterator constructs a NodeIterator that iterates over elements in b that 549 // are not in a. Returns the iterator, and a pointer to an integer recording the number 550 // of nodes seen. 551 func NewDifferenceIterator(a, b NodeIterator) (NodeIterator, *int) { 552 a.Next(true) 553 it := &differenceIterator{ 554 a: a, 555 b: b, 556 } 557 return it, &it.count 558 } 559 560 func (it *differenceIterator) Hash() common.Hash { 561 return it.b.Hash() 562 } 563 564 func (it *differenceIterator) Parent() common.Hash { 565 return it.b.Parent() 566 } 567 568 func (it *differenceIterator) Leaf() bool { 569 return it.b.Leaf() 570 } 571 572 func (it *differenceIterator) LeafKey() []byte { 573 return it.b.LeafKey() 574 } 575 576 func (it *differenceIterator) LeafBlob() []byte { 577 return it.b.LeafBlob() 578 } 579 580 func (it *differenceIterator) LeafProof() [][]byte { 581 return it.b.LeafProof() 582 } 583 584 func (it *differenceIterator) Path() []byte { 585 return it.b.Path() 586 } 587 588 func (it *differenceIterator) NodeBlob() []byte { 589 return it.b.NodeBlob() 590 } 591 592 func (it *differenceIterator) AddResolver(resolver ethdb.KeyValueReader) { 593 panic("not implemented") 594 } 595 596 func (it *differenceIterator) Next(bool) bool { 597 // Invariants: 598 // - We always advance at least one element in b. 599 // - At the start of this function, a's path is lexically greater than b's. 600 if !it.b.Next(true) { 601 return false 602 } 603 it.count++ 604 605 if it.eof { 606 // a has reached eof, so we just return all elements from b 607 return true 608 } 609 610 for { 611 switch compareNodes(it.a, it.b) { 612 case -1: 613 // b jumped past a; advance a 614 if !it.a.Next(true) { 615 it.eof = true 616 return true 617 } 618 it.count++ 619 case 1: 620 // b is before a 621 return true 622 case 0: 623 // a and b are identical; skip this whole subtree if the nodes have hashes 624 hasHash := it.a.Hash() == common.Hash{} 625 if !it.b.Next(hasHash) { 626 return false 627 } 628 it.count++ 629 if !it.a.Next(hasHash) { 630 it.eof = true 631 return true 632 } 633 it.count++ 634 } 635 } 636 } 637 638 func (it *differenceIterator) Error() error { 639 if err := it.a.Error(); err != nil { 640 return err 641 } 642 return it.b.Error() 643 } 644 645 type nodeIteratorHeap []NodeIterator 646 647 func (h nodeIteratorHeap) Len() int { return len(h) } 648 func (h nodeIteratorHeap) Less(i, j int) bool { return compareNodes(h[i], h[j]) < 0 } 649 func (h nodeIteratorHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 650 func (h *nodeIteratorHeap) Push(x interface{}) { *h = append(*h, x.(NodeIterator)) } 651 func (h *nodeIteratorHeap) Pop() interface{} { 652 n := len(*h) 653 x := (*h)[n-1] 654 *h = (*h)[0 : n-1] 655 return x 656 } 657 658 type unionIterator struct { 659 items *nodeIteratorHeap // Nodes returned are the union of the ones in these iterators 660 count int // Number of nodes scanned across all tries 661 } 662 663 // NewUnionIterator constructs a NodeIterator that iterates over elements in the union 664 // of the provided NodeIterators. Returns the iterator, and a pointer to an integer 665 // recording the number of nodes visited. 666 func NewUnionIterator(iters []NodeIterator) (NodeIterator, *int) { 667 h := make(nodeIteratorHeap, len(iters)) 668 copy(h, iters) 669 heap.Init(&h) 670 671 ui := &unionIterator{items: &h} 672 return ui, &ui.count 673 } 674 675 func (it *unionIterator) Hash() common.Hash { 676 return (*it.items)[0].Hash() 677 } 678 679 func (it *unionIterator) Parent() common.Hash { 680 return (*it.items)[0].Parent() 681 } 682 683 func (it *unionIterator) Leaf() bool { 684 return (*it.items)[0].Leaf() 685 } 686 687 func (it *unionIterator) LeafKey() []byte { 688 return (*it.items)[0].LeafKey() 689 } 690 691 func (it *unionIterator) LeafBlob() []byte { 692 return (*it.items)[0].LeafBlob() 693 } 694 695 func (it *unionIterator) LeafProof() [][]byte { 696 return (*it.items)[0].LeafProof() 697 } 698 699 func (it *unionIterator) Path() []byte { 700 return (*it.items)[0].Path() 701 } 702 703 func (it *unionIterator) NodeBlob() []byte { 704 return (*it.items)[0].NodeBlob() 705 } 706 707 func (it *unionIterator) AddResolver(resolver ethdb.KeyValueReader) { 708 panic("not implemented") 709 } 710 711 // Next returns the next node in the union of tries being iterated over. 712 // 713 // It does this by maintaining a heap of iterators, sorted by the iteration 714 // order of their next elements, with one entry for each source trie. Each 715 // time Next() is called, it takes the least element from the heap to return, 716 // advancing any other iterators that also point to that same element. These 717 // iterators are called with descend=false, since we know that any nodes under 718 // these nodes will also be duplicates, found in the currently selected iterator. 719 // Whenever an iterator is advanced, it is pushed back into the heap if it still 720 // has elements remaining. 721 // 722 // In the case that descend=false - eg, we're asked to ignore all subnodes of the 723 // current node - we also advance any iterators in the heap that have the current 724 // path as a prefix. 725 func (it *unionIterator) Next(descend bool) bool { 726 if len(*it.items) == 0 { 727 return false 728 } 729 730 // Get the next key from the union 731 least := heap.Pop(it.items).(NodeIterator) 732 733 // Skip over other nodes as long as they're identical, or, if we're not descending, as 734 // long as they have the same prefix as the current node. 735 for len(*it.items) > 0 && ((!descend && bytes.HasPrefix((*it.items)[0].Path(), least.Path())) || compareNodes(least, (*it.items)[0]) == 0) { 736 skipped := heap.Pop(it.items).(NodeIterator) 737 // Skip the whole subtree if the nodes have hashes; otherwise just skip this node 738 if skipped.Next(skipped.Hash() == common.Hash{}) { 739 it.count++ 740 // If there are more elements, push the iterator back on the heap 741 heap.Push(it.items, skipped) 742 } 743 } 744 if least.Next(descend) { 745 it.count++ 746 heap.Push(it.items, least) 747 } 748 return len(*it.items) > 0 749 } 750 751 func (it *unionIterator) Error() error { 752 for i := 0; i < len(*it.items); i++ { 753 if err := (*it.items)[i].Error(); err != nil { 754 return err 755 } 756 } 757 return nil 758 }