diff --git a/common/dbutils/history_index.go b/common/dbutils/history_index.go
index 7f7806d3d7fba93248507688c271c33b0e8dc527..660b197efd7ba3a9ea72f5f4c45eeb1e03e2ebbb 100644
--- a/common/dbutils/history_index.go
+++ b/common/dbutils/history_index.go
@@ -17,46 +17,45 @@ const (
 	MaxChunkSize = 1000
 )
 
-func NewHistoryIndex() *HistoryIndexBytes {
-	b := make(HistoryIndexBytes, LenBytes*2, 16)
-	return &b
+func NewHistoryIndex() HistoryIndexBytes {
+	return make(HistoryIndexBytes, LenBytes*2, 16)
 }
 
-func WrapHistoryIndex(b []byte) *HistoryIndexBytes {
+func WrapHistoryIndex(b []byte) HistoryIndexBytes {
 	index := HistoryIndexBytes(b)
 	if len(index) == 0 {
 		index = make(HistoryIndexBytes, LenBytes*2, 16)
 	}
-	return &index
+	return index
 }
 
 type HistoryIndexBytes []byte
 
-func (hi *HistoryIndexBytes) Decode() ([]uint64, error) {
+func (hi HistoryIndexBytes) Decode() ([]uint64, error) {
 	if hi == nil {
 		return []uint64{}, nil
 	}
-	if len(*hi) <= LenBytes*2 {
+	if len(hi) <= LenBytes*2 {
 		return []uint64{}, nil
 	}
 
-	numOfElements := binary.LittleEndian.Uint32((*hi)[0:LenBytes])
-	numOfUint32Elements := binary.LittleEndian.Uint32((*hi)[LenBytes : 2*LenBytes])
+	numOfElements := binary.LittleEndian.Uint32(hi[0:LenBytes])
+	numOfUint32Elements := binary.LittleEndian.Uint32(hi[LenBytes : 2*LenBytes])
 	decoded := make([]uint64, numOfElements)
 
 	for i := uint32(0); i < numOfElements; i++ {
 		if i < numOfUint32Elements {
-			decoded[i] = uint64(binary.LittleEndian.Uint32((*hi)[LenBytes*2+i*4 : LenBytes*2+i*4+4]))
+			decoded[i] = uint64(binary.LittleEndian.Uint32(hi[LenBytes*2+i*4 : LenBytes*2+i*4+4]))
 		} else {
-			decoded[i] = binary.LittleEndian.Uint64((*hi)[LenBytes*2+numOfUint32Elements*4+i*ItemLen : LenBytes*2+i*ItemLen+ItemLen])
+			decoded[i] = binary.LittleEndian.Uint64(hi[LenBytes*2+numOfUint32Elements*4+i*ItemLen : LenBytes*2+i*ItemLen+ItemLen])
 		}
 	}
 	return decoded, nil
 }
 
-func (hi *HistoryIndexBytes) Append(v uint64) *HistoryIndexBytes {
-	numOfElements := binary.LittleEndian.Uint32((*hi)[0:LenBytes])
-	numOfUint32Elements := binary.LittleEndian.Uint32((*hi)[LenBytes : 2*LenBytes])
+func (hi HistoryIndexBytes) Append(v uint64) HistoryIndexBytes {
+	numOfElements := binary.LittleEndian.Uint32(hi[0:LenBytes])
+	numOfUint32Elements := binary.LittleEndian.Uint32(hi[LenBytes : 2*LenBytes])
 	var b []byte
 	if v < math.MaxUint32 {
 		b = make([]byte, 4)
@@ -67,9 +66,9 @@ func (hi *HistoryIndexBytes) Append(v uint64) *HistoryIndexBytes {
 		binary.LittleEndian.PutUint64(b, v)
 	}
 
-	*hi = append(*hi, b...)
-	binary.LittleEndian.PutUint32((*hi)[0:LenBytes], numOfElements+1)
-	binary.LittleEndian.PutUint32((*hi)[LenBytes:2*LenBytes], numOfUint32Elements)
+	hi = append(hi, b...)
+	binary.LittleEndian.PutUint32(hi[0:LenBytes], numOfElements+1)
+	binary.LittleEndian.PutUint32(hi[LenBytes:2*LenBytes], numOfUint32Elements)
 	return hi
 }
 
@@ -78,9 +77,9 @@ func (hi HistoryIndexBytes) Len() uint32 {
 }
 
 //most common operation is remove one from the tail
-func (hi *HistoryIndexBytes) Remove(v uint64) *HistoryIndexBytes {
-	numOfElements := binary.LittleEndian.Uint32((*hi)[0:LenBytes])
-	numOfUint32Elements := binary.LittleEndian.Uint32((*hi)[LenBytes : 2*LenBytes])
+func (hi HistoryIndexBytes) Remove(v uint64) HistoryIndexBytes {
+	numOfElements := binary.LittleEndian.Uint32(hi[0:LenBytes])
+	numOfUint32Elements := binary.LittleEndian.Uint32(hi[LenBytes : 2*LenBytes])
 
 	var currentElement uint64
 	var elemEnd uint32
@@ -90,17 +89,17 @@ Loop:
 	for i := numOfElements; i > 0; i-- {
 		if i > numOfUint32Elements {
 			elemEnd = LenBytes*2 + numOfUint32Elements*4 + (i-numOfUint32Elements)*8
-			currentElement = binary.LittleEndian.Uint64((*hi)[elemEnd-8 : elemEnd])
+			currentElement = binary.LittleEndian.Uint64(hi[elemEnd-8 : elemEnd])
 			itemLen = 8
 		} else {
 			elemEnd = LenBytes*2 + i*4
-			currentElement = uint64(binary.LittleEndian.Uint32((*hi)[elemEnd-4 : elemEnd]))
+			currentElement = uint64(binary.LittleEndian.Uint32(hi[elemEnd-4 : elemEnd]))
 			itemLen = 4
 		}
 
 		switch {
 		case currentElement == v:
-			*hi = append((*hi)[:elemEnd-itemLen], (*hi)[elemEnd:]...)
+			hi = append(hi[:elemEnd-itemLen], hi[elemEnd:]...)
 			numOfElements--
 			if itemLen == 4 {
 				numOfUint32Elements--
@@ -111,8 +110,8 @@ Loop:
 			continue
 		}
 	}
-	binary.LittleEndian.PutUint32((*hi)[0:LenBytes], numOfElements)
-	binary.LittleEndian.PutUint32((*hi)[LenBytes:2*LenBytes], numOfUint32Elements)
+	binary.LittleEndian.PutUint32(hi[0:LenBytes], numOfElements)
+	binary.LittleEndian.PutUint32(hi[LenBytes:2*LenBytes], numOfUint32Elements)
 	return hi
 }
 
@@ -185,14 +184,7 @@ func IndexChunkKey(key []byte, blockNumber uint64) []byte {
 func IsIndexBucket(b []byte) bool {
 	return bytes.Equal(b, AccountsHistoryBucket) || bytes.Equal(b, StorageHistoryBucket)
 }
-func IsFirstChunk(b []byte) bool {
-	if len(b) == common.HashLength+8 {
-		return binary.BigEndian.Uint64(b[common.HashLength:]) == ^uint64(0)
-	} else if len(b) == common.HashLength*2+8 {
-		return binary.BigEndian.Uint64(b[common.HashLength*2:]) == ^uint64(0)
-	}
-	panic("unexpected length" + strconv.Itoa(len(b)))
-}
+
 func CheckNewIndexChunk(b []byte) bool {
 	return len(b)+8 > MaxChunkSize
 }
diff --git a/common/dbutils/history_index_test.go b/common/dbutils/history_index_test.go
index 3b1932023a4973461966b6dd356cd380a1914d5d..89f04c613db546b8462d9d366f9fa38894a748d7 100644
--- a/common/dbutils/history_index_test.go
+++ b/common/dbutils/history_index_test.go
@@ -7,8 +7,7 @@ import (
 )
 
 func TestHistoryIndex_Search1(t *testing.T) {
-	index := NewHistoryIndex()
-	index.Append(3).Append(5).Append(8)
+	index := NewHistoryIndex().Append(3).Append(5).Append(8)
 	fmt.Println(index.Decode())
 	v, _ := index.Search(1)
 	if v != 3 {
@@ -53,7 +52,7 @@ func TestHistoryIndex_Search_EmptyIndex(t *testing.T) {
 func TestHistoryIndex_Append(t *testing.T) {
 	index := NewHistoryIndex()
 	for i := uint64(1); i < 10; i++ {
-		index.Append(i)
+		index = index.Append(i)
 	}
 
 	res, err := index.Decode()
@@ -68,7 +67,7 @@ func TestHistoryIndex_Append(t *testing.T) {
 		t.Fatal()
 	}
 
-	index.Remove(9)
+	index = index.Remove(9)
 	res, err = index.Decode()
 	if err != nil {
 		t.Fatal(err)
@@ -82,7 +81,7 @@ func TestHistoryIndex_Append(t *testing.T) {
 		t.Fatal("Not equal")
 	}
 
-	index.Remove(5)
+	index = index.Remove(5)
 	res, err = index.Decode()
 	if err != nil {
 		t.Fatal(err)
@@ -96,7 +95,7 @@ func TestHistoryIndex_Append(t *testing.T) {
 		t.Fatal("Not equal")
 	}
 
-	index.Remove(1)
+	index = index.Remove(1)
 	res, err = index.Decode()
 	if err != nil {
 		t.Fatal(err)
diff --git a/core/generate_index.go b/core/generate_index.go
index a76cf830ad3a6b9db27037113d7b9235134517d7..cd85c25a44c82a003703dde25b70be2de1ff7f08 100644
--- a/core/generate_index.go
+++ b/core/generate_index.go
@@ -35,7 +35,7 @@ type IndexGenerator struct {
 }
 
 type IndexWithKey struct {
-	Val     *dbutils.HistoryIndexBytes
+	Val dbutils.HistoryIndexBytes
 }
 
 func (ig *IndexGenerator) changeSetWalker(blockNum uint64) func([]byte, []byte) error {
@@ -47,7 +47,7 @@ func (ig *IndexGenerator) changeSetWalker(blockNum uint64) func([]byte, []byte)
 			if err != nil && err != ethdb.ErrKeyNotFound {
 				return err
 			}
-			var index *dbutils.HistoryIndexBytes
+			var index dbutils.HistoryIndexBytes
 
 			if len(indexBytes) == 0 {
 				index = dbutils.NewHistoryIndex()
@@ -58,18 +58,18 @@ func (ig *IndexGenerator) changeSetWalker(blockNum uint64) func([]byte, []byte)
 			}
 
 			indexes = append(indexes, IndexWithKey{
-				Val:     index,
+				Val: index,
 			})
 			ig.cache[string(k)] = indexes
 		}
 
 		lastIndex := indexes[len(indexes)-1]
-		if dbutils.CheckNewIndexChunk(*lastIndex.Val) {
+		if dbutils.CheckNewIndexChunk(lastIndex.Val) {
 			lastIndex.Val = dbutils.NewHistoryIndex()
 			indexes = append(indexes, lastIndex)
 			ig.cache[string(k)] = indexes
 		}
-		lastIndex.Val.Append(blockNum)
+		lastIndex.Val = lastIndex.Val.Append(blockNum)
 		return nil
 	}
 }
@@ -109,7 +109,7 @@ func (ig *IndexGenerator) GenerateIndex() error {
 					return err
 				}
 
-				if err := tuples.Append(ig.bucketToWrite, chunkKey, *val.Val); err != nil {
+				if err := tuples.Append(ig.bucketToWrite, chunkKey, val.Val); err != nil {
 					return err
 				}
 
diff --git a/core/state/database.go b/core/state/database.go
index 1b705d92d4a5ff481c9e884686a6f96041cf1e5e..a470ef670ff09163cc4f58fd5c8f3c3ce4fcab5f 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -945,12 +945,12 @@ func (tds *TrieDbState) deleteTimestamp(timestamp uint64) error {
 			if err != nil {
 				return err
 			}
-			index.Remove(timestamp)
+			index = index.Remove(timestamp)
 
 			if index.Len() == 0 {
 				return tds.db.Delete(dbutils.AccountsHistoryBucket, chunkKey)
 			}
-			return tds.db.Put(dbutils.AccountsHistoryBucket, chunkKey, *index)
+			return tds.db.Put(dbutils.AccountsHistoryBucket, chunkKey, index)
 		})
 		if innerErr != nil {
 			return innerErr
@@ -976,12 +976,12 @@ func (tds *TrieDbState) deleteTimestamp(timestamp uint64) error {
 				return err
 			}
 
-			index.Remove(timestamp)
+			index = index.Remove(timestamp)
 
 			if index.Len() == 0 {
 				return tds.db.Delete(dbutils.StorageHistoryBucket, chunkKey)
 			}
-			return tds.db.Put(dbutils.StorageHistoryBucket, chunkKey, *index)
+			return tds.db.Put(dbutils.StorageHistoryBucket, chunkKey, index)
 		})
 		if innerErr != nil {
 			return innerErr
diff --git a/core/state/db_state_writer.go b/core/state/db_state_writer.go
index 0019878e5df8eaf13744df240b844d69e7369011..5f558252527f5f4cf5e6980e896d30ece75890f4 100644
--- a/core/state/db_state_writer.go
+++ b/core/state/db_state_writer.go
@@ -171,28 +171,35 @@ func (dsw *DbStateWriter) WriteHistory() error {
 
 func (dsw *DbStateWriter) writeIndex(changes *changeset.ChangeSet, bucket []byte) error {
 	for _, change := range changes.Changes {
-		indexBytes, err := dsw.tds.db.GetIndexChunk(bucket, change.Key, dsw.tds.blockNr)
+		currentChunkKey := dbutils.IndexChunkKey(change.Key, ^uint64(0))
+		indexBytes, err := dsw.tds.db.Get(bucket, currentChunkKey)
 		if err != nil && err != ethdb.ErrKeyNotFound {
 			return fmt.Errorf("find chunk failed: %w", err)
 		}
 
-		var index *dbutils.HistoryIndexBytes
+		var index dbutils.HistoryIndexBytes
 		if len(indexBytes) == 0 {
 			index = dbutils.NewHistoryIndex()
 		} else if dbutils.CheckNewIndexChunk(indexBytes) {
+			// Chunk overflow, need to write the "old" current chunk under its key derived from the last element
+			index = dbutils.WrapHistoryIndex(indexBytes)
+			indexKey, err := index.Key(change.Key)
+			if err != nil {
+				return err
+			}
+			// Flush the old chunk
+			if err := dsw.tds.db.Put(bucket, indexKey, index); err != nil {
+				return err
+			}
+			// Start a new chunk
 			index = dbutils.NewHistoryIndex()
 		} else {
 			index = dbutils.WrapHistoryIndex(indexBytes)
 		}
 
-		index.Append(dsw.tds.blockNr)
-
-		indexKey, err := index.Key(change.Key)
-		if err != nil {
-			return err
-		}
+		index = index.Append(dsw.tds.blockNr)
 
-		if err := dsw.tds.db.Put(bucket, indexKey, *index); err != nil {
+		if err := dsw.tds.db.Put(bucket, currentChunkKey, index); err != nil {
 			return err
 		}
 	}
diff --git a/ethdb/bolt_db.go b/ethdb/bolt_db.go
index b8bfb2bce432cbe860ef1c5cd96302e778adea19..4179a37a899dae6852f95613a21ae3a03772ea0b 100644
--- a/ethdb/bolt_db.go
+++ b/ethdb/bolt_db.go
@@ -374,6 +374,9 @@ func (db *BoltDatabase) walkAsOfThinAccounts(startkey []byte, fixedbits uint, ti
 			common.HashLength+8, /* part3start */
 		)
 		k, v := mainCursor.Seek(startkey)
+		for k != nil && len(k) > common.HashLength {
+			k, v = mainCursor.Next()
+		}
 		hK, tsEnc, _, hV := historyCursor.Seek()
 		if hK != nil {
 			ts := binary.BigEndian.Uint64(tsEnc)
@@ -431,20 +434,22 @@ func (db *BoltDatabase) walkAsOfThinAccounts(startkey []byte, fixedbits uint, ti
 							timestamp,
 						)
 					}
-					var acc accounts.Account
-					if err2 := acc.DecodeForStorage(data); err2 != nil {
-						return err2
-					}
-					if acc.Incarnation > 0 && acc.IsEmptyCodeHash() {
-						codeBucket := tx.Bucket(dbutils.ContractCodeBucket)
-						codeHash, _ := codeBucket.Get(dbutils.GenerateStoragePrefix(common.BytesToHash(hK), acc.Incarnation))
-						if len(codeHash) > 0 {
-							acc.CodeHash = common.BytesToHash(codeHash)
+					if len(data) > 0 { // Skip accounts did not exist
+						var acc accounts.Account
+						if err2 := acc.DecodeForStorage(data); err2 != nil {
+							return err2
 						}
-						data = make([]byte, acc.EncodingLengthForStorage())
-						acc.EncodeForStorage(data)
+						if acc.Incarnation > 0 && acc.IsEmptyCodeHash() {
+							codeBucket := tx.Bucket(dbutils.ContractCodeBucket)
+							codeHash, _ := codeBucket.Get(dbutils.GenerateStoragePrefix(common.BytesToHash(hK), acc.Incarnation))
+							if len(codeHash) > 0 {
+								acc.CodeHash = common.BytesToHash(codeHash)
+							}
+							data = make([]byte, acc.EncodingLengthForStorage())
+							acc.EncodeForStorage(data)
+						}
+						goOn, err = walker(hK, data)
 					}
-					goOn, err = walker(hK, data)
 				} else if cmp == 0 {
 					goOn, err = walker(k, v)
 				}
@@ -452,6 +457,9 @@ func (db *BoltDatabase) walkAsOfThinAccounts(startkey []byte, fixedbits uint, ti
 			if goOn {
 				if cmp <= 0 {
 					k, v = mainCursor.Next()
+					for k != nil && len(k) > common.HashLength {
+						k, v = mainCursor.Next()
+					}
 				}
 				if cmp >= 0 {
 					hK, tsEnc, _, hV = historyCursor.Next()