Skip to content

Commit e4ac9f4

Browse files
committed
triedb/pathdb: polish code
1 parent a3b20da commit e4ac9f4

File tree

5 files changed

+65
-25
lines changed

5 files changed

+65
-25
lines changed

triedb/pathdb/generate.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ func (g *generator) generateAccounts(ctx *generatorContext, accMarker []byte) er
738738
return err
739739
}
740740
}
741-
// Some account counter, unmark the marker
741+
// Some account processed, unmark the marker
742742
accMarker = nil
743743
return nil
744744
}
@@ -784,7 +784,7 @@ func (g *generator) generate(ctx *generatorContext) {
784784
// Even if the snapshot data is updated during the interruption (before
785785
// or at the marker), the assumption is still held.
786786
// For the account or storage slot at the interruption, they will be
787-
// counter twice by the generator(they are already counter in the
787+
// processed twice by the generator(they are already processed in the
788788
// last run) but it's fine.
789789
var (
790790
accMarker, _ = splitMarker(g.progress)

triedb/pathdb/history_index.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func (r *indexReader) refresh() error {
122122
}
123123

124124
// readGreaterThan locates the first element that is greater than the specified
125-
// value. If no such element is found, MaxUint64 is returned.
125+
// id. If no such element is found, MaxUint64 is returned.
126126
func (r *indexReader) readGreaterThan(id uint64) (uint64, error) {
127127
index := sort.Search(len(r.descList), func(i int) bool {
128128
return id < r.descList[i].max

triedb/pathdb/history_index_block.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,17 @@ func (d *indexBlockDesc) decode(blob []byte) {
9898
// Each chunk begins with the full value of the first integer, followed by
9999
// subsequent integers representing the differences between the current value
100100
// and the preceding one. Integers are encoded with variable-size for best
101-
// storage efficiency.
101+
// storage efficiency. Each chunk can be illustrated as below.
102+
//
103+
// Restart ---> +----------------+
104+
// | Full integer |
105+
// +----------------+
106+
// | Diff with prev |
107+
// +----------------+
108+
// | ... |
109+
// +----------------+
110+
// | Diff with prev |
111+
// +----------------+
102112
//
103113
// Empty index block is regarded as invalid.
104114
func parseIndexBlock(blob []byte) ([]uint32, []byte, error) {
@@ -118,6 +128,8 @@ func parseIndexBlock(blob []byte) ([]uint32, []byte, error) {
118128
restart := binary.BigEndian.Uint32(blob[len(blob)-int(i+1)*4:])
119129
restarts = append(restarts, restart)
120130
}
131+
// Validate that restart points are strictly ordered and within the valid
132+
// data range.
121133
var prev uint32
122134
for i := 0; i < len(restarts); i++ {
123135
if i != 0 {
@@ -198,18 +210,21 @@ func (br *blockReader) readGreaterThan(id uint64) (uint64, error) {
198210
}
199211
pos += n
200212
}
213+
// The element which is greater than specified id is not found.
201214
if index == len(br.restarts) {
202215
return math.MaxUint64, nil
203216
}
217+
// The element which is the first one greater than the specified id
218+
// is exactly the one located at the restart point.
204219
item, _ := binary.Uvarint(br.data[br.restarts[index]:])
205220
return item, nil
206221
}
207222

208223
type blockWriter struct {
209-
desc *indexBlockDesc
210-
restarts []uint32
211-
scratch []byte
212-
data []byte
224+
desc *indexBlockDesc // Descriptor of the block
225+
restarts []uint32 // Offsets into the data slice, marking the start of each section
226+
scratch []byte // Buffer used for encoding full integers or value differences
227+
data []byte // Aggregated encoded data slice
213228
}
214229

215230
func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) {
@@ -234,16 +249,18 @@ func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) {
234249
}
235250

236251
// append adds a new element to the block. The new element must be greater than
237-
// the previously one.
252+
// the previous one. The provided ID is assumed to always be greater than 0.
238253
func (b *blockWriter) append(id uint64) error {
239254
if id == 0 {
240255
return errors.New("invalid zero id")
241256
}
242257
if id <= b.desc.max {
243258
return fmt.Errorf("append element out of order, last: %d, this: %d", b.desc.max, id)
244259
}
260+
// Rotate the current restart section if it's full
245261
if b.desc.entries%indexBlockRestartLen == 0 {
246-
// Rotate the current restart range if it's full
262+
// Save the offset within the data slice as the restart point
263+
// for the next section.
247264
b.restarts = append(b.restarts, uint32(len(b.data)))
248265

249266
// The restart point item can either be encoded in variable
@@ -256,8 +273,10 @@ func (b *blockWriter) append(id uint64) error {
256273
n := binary.PutUvarint(b.scratch[0:], id)
257274
b.data = append(b.data, b.scratch[:n]...)
258275
} else {
259-
// Non-head elements within a restart range are encoded using
260-
// their difference from the preceding element.
276+
// The current section is not full, append the element.
277+
// The element which is not the first one in the section
278+
// is encoded using the value difference from the preceding
279+
// element.
261280
n := binary.PutUvarint(b.scratch[0:], id-b.desc.max)
262281
b.data = append(b.data, b.scratch[:n]...)
263282
}
@@ -310,16 +329,17 @@ func (b *blockWriter) sectionLast(section int) uint64 {
310329

311330
// sectionSearch looks up the specified value in the given section,
312331
// the position and the preceding value will be returned if found.
313-
func (b *blockWriter) sectionSearch(section int, n uint64) (prev uint64, pos int) {
332+
func (b *blockWriter) sectionSearch(section int, n uint64) (found bool, prev uint64, pos int) {
314333
b.scanSection(section, func(v uint64, p int) bool {
315334
if n == v {
316335
pos = p
317-
return true
336+
found = true
337+
return true // terminate iteration
318338
}
319339
prev = v
320-
return false
340+
return false // continue iteration
321341
})
322-
return prev, pos
342+
return found, prev, pos
323343
}
324344

325345
// pop removes the last element from the block. The assumption is held that block
@@ -351,7 +371,10 @@ func (b *blockWriter) pop(id uint64) error {
351371
}
352372
// Look up the element preceding the one to be popped, in order to update
353373
// the maximum element in the block.
354-
prev, pos := b.sectionSearch(len(b.restarts)-1, id)
374+
found, prev, pos := b.sectionSearch(len(b.restarts)-1, id)
375+
if !found {
376+
return fmt.Errorf("pop element is not found, last: %d, this: %d", b.desc.max, id)
377+
}
355378
b.desc.max = prev
356379
b.data = b.data[:pos]
357380
b.desc.entries -= 1

triedb/pathdb/history_indexer.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ func newBatchIndexer(db ethdb.KeyValueStore, delete bool) *batchIndexer {
5757
// process iterates through the accounts and their associated storage slots in the
5858
// state history, tracking the mapping between state and history IDs.
5959
func (b *batchIndexer) process(h *history, historyID uint64) error {
60-
buf := crypto.NewKeccakState()
6160
for _, address := range h.accountList {
6261
b.counter += 1
6362
b.accounts[address] = append(b.accounts[address], historyID)
@@ -72,7 +71,7 @@ func (b *batchIndexer) process(h *history, historyID uint64) error {
7271
// conversion from storage key to hash is necessary for non-v0 histories.
7372
slotHash := slotKey
7473
if h.meta.version != stateHistoryV0 {
75-
slotHash = crypto.HashData(buf, slotKey.Bytes())
74+
slotHash = crypto.Keccak256Hash(slotKey.Bytes())
7675
}
7776
b.storages[address][slotHash] = append(b.storages[address][slotHash], historyID)
7877
}
@@ -225,6 +224,14 @@ type interruptSignal struct {
225224
result chan error
226225
}
227226

227+
// indexIniter is responsible for completing the indexing of remaining state
228+
// histories in batch. It runs as a one-time background thread and terminates
229+
// once all available state histories are indexed.
230+
//
231+
// Afterward, new state histories should be indexed synchronously alongside
232+
// the state data itself, ensuring both the history and its index are available.
233+
// If a state history is removed due to a rollback, the associated indexes should
234+
// be unmarked accordingly.
228235
type indexIniter struct {
229236
disk ethdb.KeyValueStore
230237
freezer ethdb.AncientStore
@@ -422,7 +429,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
422429
)
423430
// Override the ETA if larger than the largest until now
424431
eta := time.Duration(left/speed) * time.Millisecond
425-
log.Info("Indexing state history", "counter", done, "left", left, "eta", common.PrettyDuration(eta))
432+
log.Info("Indexing state history", "processed", done, "left", left, "eta", common.PrettyDuration(eta))
426433
}
427434
}
428435
// Check interruption signal and abort process if it's fired
@@ -450,13 +457,16 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
450457
// process is finished, all state histories are marked as fully indexed,
451458
// enabling handling of requests for historical states. Thereafter, any new
452459
// state histories must be indexed or unindexed synchronously, ensuring that
453-
// the history index is created or removed with the corresponding state history.
460+
// the history index is created or removed along with the corresponding
461+
// state history.
454462
type historyIndexer struct {
455463
initer *indexIniter
456464
disk ethdb.KeyValueStore
457465
freezer ethdb.AncientStore
458466
}
459467

468+
// newHistoryIndexer constructs the history indexer and launches the background
469+
// initer to complete the indexing of any remaining state histories.
460470
func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64) *historyIndexer {
461471
return &historyIndexer{
462472
initer: newIndexIniter(disk, freezer, lastHistoryID),

triedb/pathdb/history_reader.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,16 @@ import (
3232
// stateIdent represents the identifier of a state element, which can be
3333
// either an account or a storage slot.
3434
type stateIdent struct {
35-
account bool
36-
address common.Address
37-
storageHash common.Hash // null if account is true, the hash of the raw storage slot key
35+
account bool
36+
address common.Address
37+
38+
// The hash of the storage slot key. This is used instead of the raw slot key
39+
// because, in legacy state histories (prior to the Cancun fork), the slot
40+
// identifier is the hash of the key, and the original key (preimage) cannot
41+
// be recovered. To maintain backward compatibility, the key hash is used.
42+
//
43+
// This field is null if the identifier refers to account data.
44+
storageHash common.Hash
3845
}
3946

4047
// String returns the string format state identifier.
@@ -122,7 +129,7 @@ func newIndexReaderWithLimitTag(db ethdb.KeyValueReader, state stateIdent) (*ind
122129
}
123130

124131
// readGreaterThan locates the first element that is greater than the specified
125-
// value. If no such element is found, MaxUint64 is returned.
132+
// id. If no such element is found, MaxUint64 is returned.
126133
//
127134
// Note: It is possible that additional histories have been indexed since the
128135
// reader was created. The reader should be refreshed as needed to load the

0 commit comments

Comments
 (0)