From 81207490bf774b87ab5411e14ededc4c2145406c Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 15 Mar 2022 14:35:18 +0800 Subject: [PATCH 1/4] trie: fix the memory leak in trie iterator In trie iterator a batch of live nodes will be tracked and be poped when it's iterated. However the poped node state should be explictly set to nil in order to be garbage collected. --- trie/iterator.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/trie/iterator.go b/trie/iterator.go index 1fbf991af09e..1bf3e75231c7 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -425,7 +425,7 @@ func findChild(n *fullNode, index int, path []byte, ancestor common.Hash) (node, 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. + // Full node, move to the first non-nil child. if child, state, path, index := findChild(node, parent.index+1, it.path, ancestor); child != nil { parent.index = index - 1 return state, path, true @@ -503,8 +503,9 @@ func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path [] } func (it *nodeIterator) pop() { - parent := it.stack[len(it.stack)-1] - it.path = it.path[:parent.pathlen] + last := it.stack[len(it.stack)-1] + it.path = it.path[:last.pathlen] + it.stack[len(it.stack)-1] = nil it.stack = it.stack[:len(it.stack)-1] } From c5d78fa0491a900af6f7045b09484f1b36584767 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 15 Mar 2022 14:43:42 +0800 Subject: [PATCH 2/4] trie: fix empty trie iterator --- trie/iterator.go | 8 +++++--- trie/iterator_test.go | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/trie/iterator.go b/trie/iterator.go index 1bf3e75231c7..b0b7ce0d5881 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -20,7 +20,6 @@ import ( "bytes" "container/heap" "errors" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" ) @@ -154,8 +153,11 @@ func (e seekError) Error() string { } func newNodeIterator(trie *Trie, start []byte) NodeIterator { - if trie.Hash() == emptyState { - return new(nodeIterator) + if trie.Hash() == emptyRoot { + return &nodeIterator{ + trie: trie, + err: errIteratorEnd, + } } it := &nodeIterator{trie: trie} it.err = it.seek(start) diff --git a/trie/iterator_test.go b/trie/iterator_test.go index 1a9a5e80e588..53bdd39200b1 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -29,6 +29,20 @@ import ( "github.com/ethereum/go-ethereum/ethdb/memorydb" ) +func TestEmptyIterator(t *testing.T) { + trie := newEmpty() + iter := trie.NodeIterator(nil) + + seen := make(map[string]struct{}) + for iter.Next(true) { + seen[string(iter.Path())] = struct{}{} + fmt.Println("iter.path", iter.Path(), "val", iter.NodeBlob()) + } + if len(seen) != 0 { + t.Fatal("Unexpected trie node iterated") + } +} + func TestIterator(t *testing.T) { trie := newEmpty() vals := []struct{ k, v string }{ From f7ef780f5f65b6ee4d4bf0ac52ffa536a238eaa2 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 15 Mar 2022 14:47:58 +0800 Subject: [PATCH 3/4] trie: fix goimport --- trie/iterator.go | 1 + 1 file changed, 1 insertion(+) diff --git a/trie/iterator.go b/trie/iterator.go index b0b7ce0d5881..e0006ee05e3b 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -20,6 +20,7 @@ import ( "bytes" "container/heap" "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" ) From 8c95e750e1a1e94c5a9603acdf4d8ede1aa93b5a Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 15 Mar 2022 16:14:31 +0800 Subject: [PATCH 4/4] trie: remove debug line --- trie/iterator_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/trie/iterator_test.go b/trie/iterator_test.go index 53bdd39200b1..9a46e9b99548 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -36,7 +36,6 @@ func TestEmptyIterator(t *testing.T) { seen := make(map[string]struct{}) for iter.Next(true) { seen[string(iter.Path())] = struct{}{} - fmt.Println("iter.path", iter.Path(), "val", iter.NodeBlob()) } if len(seen) != 0 { t.Fatal("Unexpected trie node iterated")