From e303aeb5ee6b964a9225543e82fbed1a56f64be6 Mon Sep 17 00:00:00 2001
From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com>
Date: Sat, 20 Mar 2021 10:38:45 +0100
Subject: [PATCH] Simple test for layout of TrieOfAccountsBucket  (#1563)

---
 common/dbutils/bucket.go                 |  2 +-
 eth/stagedsync/stage_interhashes_test.go | 65 ++++++++++++++++++++++++
 ethdb/kv_lmdb.go                         |  7 ++-
 ethdb/kv_mdbx.go                         |  7 ++-
 4 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 eth/stagedsync/stage_interhashes_test.go

diff --git a/common/dbutils/bucket.go b/common/dbutils/bucket.go
index a535e9b5da..08e9f1bcc5 100644
--- a/common/dbutils/bucket.go
+++ b/common/dbutils/bucket.go
@@ -110,7 +110,7 @@ hasHash - mark prefixes which hashes are saved in current trie_account record (a
         v                    v                              v                         v                  v
 +------------------+    +----------------------+     +---------------+        +---------------+  +---------------+
 | Account:         |    | BranchNode: 0x0B0004 |     | Account:      |        | Account:      |  | Account:      |
-| 0x0B0000...      |    | has no record in     |     | 0x0B01...     |        | 0x0B0301...   |  | 0x050304...   |
+| 0x0B0000...      |    | has no record in     |     | 0x0B01...     |        | 0x0B0301...   |  | 0x0B0304...   |
 | in HashedAccount |    |     TrieAccount      |     |               |        |               |  |               |
 +------------------+    +----------------------+     +---------------+        +---------------+  +---------------+
                            |                |
diff --git a/eth/stagedsync/stage_interhashes_test.go b/eth/stagedsync/stage_interhashes_test.go
new file mode 100644
index 0000000000..25e2d95fbd
--- /dev/null
+++ b/eth/stagedsync/stage_interhashes_test.go
@@ -0,0 +1,65 @@
+package stagedsync
+
+import (
+	"testing"
+
+	"github.com/ledgerwatch/turbo-geth/common"
+	"github.com/ledgerwatch/turbo-geth/common/dbutils"
+	"github.com/ledgerwatch/turbo-geth/core/types/accounts"
+	"github.com/ledgerwatch/turbo-geth/ethdb"
+	"github.com/ledgerwatch/turbo-geth/turbo/trie"
+	"github.com/stretchr/testify/assert"
+)
+
+func addTestAccount(db ethdb.Putter, hash common.Hash, balance uint64) error {
+	acc := accounts.NewAccount()
+	acc.Balance.SetUint64(balance)
+	encoded := make([]byte, acc.EncodingLengthForStorage())
+	acc.EncodeForStorage(encoded)
+	return db.Put(dbutils.HashedAccountsBucket, hash[:], encoded)
+}
+
+func TestTrieOfAccountsLayout(t *testing.T) {
+	db := ethdb.NewMemDatabase()
+
+	hash1 := common.HexToHash("0xB000000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash1, 300_000_000_000))
+
+	hash2 := common.HexToHash("0xB040000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash2, 100_000_000_000))
+
+	hash3 := common.HexToHash("0xB041000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash3, 200_000_000_000))
+
+	hash4 := common.HexToHash("0xB100000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash4, 400_000_000_000))
+
+	hash5 := common.HexToHash("0xB310000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash5, 800_000_000_000))
+
+	hash6 := common.HexToHash("0xB340000000000000000000000000000000000000000000000000000000000000")
+	assert.Nil(t, addTestAccount(db, hash6, 100_000_000_000))
+
+	err := RegenerateIntermediateHashes("IH", db, false /* checkRoot */, nil /* cache */, getTmpDir(), common.Hash{} /* expectedRootHash */, nil /* quit */)
+	assert.Nil(t, err)
+
+	account_trie := make(map[string][]byte)
+
+	err = db.Walk(dbutils.TrieOfAccountsBucket, []byte{}, 0, func(k, v []byte) (bool, error) {
+		account_trie[string(k)] = v
+		return true, nil
+	})
+	assert.Nil(t, err)
+
+	assert.Equal(t, 2, len(account_trie))
+
+	hasState1, hasTree1, hasHash1, _, _ := trie.UnmarshalTrieNode(account_trie[string(common.FromHex("0B"))])
+	assert.Equal(t, uint16(0b1011), hasState1)
+	assert.Equal(t, uint16(0b0001), hasTree1)
+	assert.Equal(t, uint16(0b1001), hasHash1)
+
+	hasState2, hasTree2, hasHash2, _, _ := trie.UnmarshalTrieNode(account_trie[string(common.FromHex("0B00"))])
+	assert.Equal(t, uint16(0b10001), hasState2)
+	assert.Equal(t, uint16(0b00000), hasTree2)
+	assert.Equal(t, uint16(0b10000), hasHash2)
+}
diff --git a/ethdb/kv_lmdb.go b/ethdb/kv_lmdb.go
index 796a0e17fe..968a92f5f0 100644
--- a/ethdb/kv_lmdb.go
+++ b/ethdb/kv_lmdb.go
@@ -1320,8 +1320,13 @@ func (c *LmdbCursor) Append(k []byte, v []byte) error {
 func (c *LmdbCursor) Close() {
 	if c.c != nil {
 		c.c.Close()
+		l := len(c.tx.cursors)
+		if l == 0 {
+			c.c = nil
+			return
+		}
 		//TODO: Find a better solution to avoid the leak?
-		newCursors := make([]*lmdb.Cursor, len(c.tx.cursors)-1)
+		newCursors := make([]*lmdb.Cursor, l-1)
 		i := 0
 		for _, cc := range c.tx.cursors {
 			if cc != c.c {
diff --git a/ethdb/kv_mdbx.go b/ethdb/kv_mdbx.go
index eb5e26447a..b7d8b18d43 100644
--- a/ethdb/kv_mdbx.go
+++ b/ethdb/kv_mdbx.go
@@ -1375,8 +1375,13 @@ func (c *MdbxCursor) Append(k []byte, v []byte) error {
 func (c *MdbxCursor) Close() {
 	if c.c != nil {
 		c.c.Close()
+		l := len(c.tx.cursors)
+		if l == 0 {
+			c.c = nil
+			return
+		}
 		//TODO: Find a better solution to avoid the leak?
-		newCursors := make([]*mdbx.Cursor, len(c.tx.cursors)-1)
+		newCursors := make([]*mdbx.Cursor, l-1)
 		i := 0
 		for _, cc := range c.tx.cursors {
 			if cc != c.c {
-- 
GitLab