Skip to content

Commit 2c9785e

Browse files
committed
fix: int64 instead of uint64
Signed-off-by: jsvisa <[email protected]>
1 parent 997cb2e commit 2c9785e

File tree

1 file changed

+67
-81
lines changed

1 file changed

+67
-81
lines changed

core/state/statesize.go

Lines changed: 67 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package state
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"sync/atomic"
2223
"time"
2324

@@ -26,42 +27,33 @@ import (
2627
"github.com/ethereum/go-ethereum/crypto"
2728
"github.com/ethereum/go-ethereum/ethdb"
2829
"github.com/ethereum/go-ethereum/log"
29-
"github.com/ethereum/go-ethereum/rlp"
3030
"github.com/ethereum/go-ethereum/triedb"
3131
"golang.org/x/sync/errgroup"
3232
)
3333

34-
// StateSizeMetrics represents the current state size statistics
35-
type StateSizeMetrics struct {
34+
// stateSizeMetrics represents the current state size statistics
35+
type stateSizeMetrics struct {
3636
Root common.Hash // Root hash of the state trie
37-
AccountCount uint64
38-
AccountBytes uint64
39-
StorageCount uint64
40-
StorageBytes uint64
41-
TrieNodeCount uint64
42-
TrieNodeBytes uint64
43-
ContractCount uint64
44-
ContractBytes uint64
37+
AccountCount int64
38+
AccountBytes int64
39+
StorageCount int64
40+
StorageBytes int64
41+
TrieNodeCount int64
42+
TrieNodeBytes int64
43+
ContractCount int64
44+
ContractBytes int64
4545
}
4646

4747
// StateSizeGenerator handles the initialization and tracking of state size metrics
4848
type StateSizeGenerator struct {
49-
db ethdb.KeyValueStore
50-
triedb *triedb.Database
51-
52-
// Generator state
53-
abort chan struct{}
54-
done chan struct{}
55-
56-
// Async message channel for updates
57-
updateChan chan *stateUpdate
58-
59-
// Metrics state (only modified by generate() goroutine)
60-
metrics *StateSizeMetrics
61-
buffered *StateSizeMetrics
62-
63-
// Initialization state
64-
initialized atomic.Bool
49+
db ethdb.KeyValueStore
50+
triedb *triedb.Database
51+
abort chan struct{}
52+
done chan struct{}
53+
updateChan chan *stateUpdate // Async message channel for updates
54+
metrics *stateSizeMetrics
55+
buffered *stateSizeMetrics
56+
initialized atomic.Bool // Initialization state
6557
}
6658

6759
// NewStateSizeGenerator creates a new state size generator and starts it automatically
@@ -72,8 +64,8 @@ func NewStateSizeGenerator(db ethdb.KeyValueStore, triedb *triedb.Database, root
7264
abort: make(chan struct{}),
7365
done: make(chan struct{}),
7466
updateChan: make(chan *stateUpdate, 1000), // Buffered channel for updates
75-
metrics: &StateSizeMetrics{Root: root},
76-
buffered: &StateSizeMetrics{Root: root},
67+
metrics: &stateSizeMetrics{Root: root},
68+
buffered: &stateSizeMetrics{Root: root},
7769
}
7870

7971
// Start the generator automatically
@@ -82,13 +74,12 @@ func NewStateSizeGenerator(db ethdb.KeyValueStore, triedb *triedb.Database, root
8274
return g
8375
}
8476

85-
// Stop terminates the background generation
77+
// Stop terminates the background generation and persists the metrics.
8678
func (g *StateSizeGenerator) Stop() {
8779
close(g.abort)
8880

8981
<-g.done
9082

91-
// Persist metrics after all the goroutines were stopped
9283
g.persistMetrics()
9384
}
9485

@@ -119,7 +110,20 @@ func (g *StateSizeGenerator) generate() {
119110

120111
case <-initDone:
121112
// Initialization completed, merge buffered metrics
122-
g.mergeBufferedMetrics()
113+
if g.buffered != nil {
114+
log.Info("Merging buffered metrics into main metrics")
115+
g.metrics.Root = g.buffered.Root
116+
g.metrics.AccountCount += g.buffered.AccountCount
117+
g.metrics.AccountBytes += g.buffered.AccountBytes
118+
g.metrics.StorageCount += g.buffered.StorageCount
119+
g.metrics.StorageBytes += g.buffered.StorageBytes
120+
g.metrics.TrieNodeCount += g.buffered.TrieNodeCount
121+
g.metrics.TrieNodeBytes += g.buffered.TrieNodeBytes
122+
g.metrics.ContractCount += g.buffered.ContractCount
123+
g.metrics.ContractBytes += g.buffered.ContractBytes
124+
125+
g.buffered = nil
126+
}
123127
initDone = nil // Clear the channel to prevent future selects
124128
}
125129
}
@@ -174,30 +178,12 @@ func (g *StateSizeGenerator) initialize() chan struct{} {
174178
return initDone
175179
}
176180

177-
// mergeBufferedMetrics merges buffered metrics into main metrics
178-
func (g *StateSizeGenerator) mergeBufferedMetrics() {
179-
if g.buffered != nil {
180-
log.Info("Merging buffered metrics into main metrics")
181-
g.metrics.Root = g.buffered.Root
182-
g.metrics.AccountCount += g.buffered.AccountCount
183-
g.metrics.AccountBytes += g.buffered.AccountBytes
184-
g.metrics.StorageCount += g.buffered.StorageCount
185-
g.metrics.StorageBytes += g.buffered.StorageBytes
186-
g.metrics.TrieNodeCount += g.buffered.TrieNodeCount
187-
g.metrics.TrieNodeBytes += g.buffered.TrieNodeBytes
188-
g.metrics.ContractCount += g.buffered.ContractCount
189-
g.metrics.ContractBytes += g.buffered.ContractBytes
190-
191-
g.buffered = nil
192-
}
193-
}
194-
195181
// handleUpdate processes a single update with proper root continuity checking
196182
func (g *StateSizeGenerator) handleUpdate(update *stateUpdate, initialized bool) {
197183
// Calculate the diff
198184
diff := g.calculateUpdateDiff(update)
199185

200-
var targetMetrics *StateSizeMetrics
186+
var targetMetrics *stateSizeMetrics
201187
if initialized {
202188
targetMetrics = g.metrics
203189
} else {
@@ -233,8 +219,8 @@ func (g *StateSizeGenerator) handleUpdate(update *stateUpdate, initialized bool)
233219
}
234220

235221
// calculateUpdateDiff calculates the diff for a state update
236-
func (g *StateSizeGenerator) calculateUpdateDiff(update *stateUpdate) StateSizeMetrics {
237-
var diff StateSizeMetrics
222+
func (g *StateSizeGenerator) calculateUpdateDiff(update *stateUpdate) stateSizeMetrics {
223+
var diff stateSizeMetrics
238224

239225
// Calculate account changes
240226
for addr, oldValue := range update.accountsOrigin {
@@ -252,7 +238,7 @@ func (g *StateSizeGenerator) calculateUpdateDiff(update *stateUpdate) StateSizeM
252238
diff.AccountCount += 1
253239
diff.AccountBytes += common.HashLength
254240
}
255-
diff.AccountBytes += uint64(len(newValue) - len(oldValue))
241+
diff.AccountBytes += int64(len(newValue) - len(oldValue))
256242
}
257243

258244
// Calculate storage changes
@@ -285,7 +271,7 @@ func (g *StateSizeGenerator) calculateUpdateDiff(update *stateUpdate) StateSizeM
285271
diff.StorageCount += 1
286272
diff.StorageBytes += common.HashLength
287273
}
288-
diff.StorageBytes += uint64(len(newValue) - len(oldValue))
274+
diff.StorageBytes += int64(len(newValue) - len(oldValue))
289275
}
290276
}
291277

@@ -294,21 +280,21 @@ func (g *StateSizeGenerator) calculateUpdateDiff(update *stateUpdate) StateSizeM
294280
for path, n := range subset.Nodes {
295281
if len(n.Blob) == 0 {
296282
diff.TrieNodeCount -= 1
297-
diff.TrieNodeBytes -= uint64(len(path) + common.HashLength)
283+
diff.TrieNodeBytes -= int64(len(path) + common.HashLength)
298284
}
299285
prev, ok := subset.Origins[path]
300286
if ok {
301287
diff.TrieNodeCount += 1
302-
diff.TrieNodeBytes += uint64(len(path) + common.HashLength)
288+
diff.TrieNodeBytes += int64(len(path) + common.HashLength)
303289
}
304-
diff.TrieNodeBytes += uint64(len(n.Blob) - len(prev))
290+
diff.TrieNodeBytes += int64(len(n.Blob) - len(prev))
305291
}
306292
}
307293

308294
// Calculate code changes
309295
for _, code := range update.codes {
310296
diff.ContractCount += 1
311-
diff.ContractBytes += uint64(len(code.blob) + common.HashLength)
297+
diff.ContractBytes += int64(len(code.blob) + common.HashLength)
312298
}
313299

314300
return diff
@@ -333,15 +319,15 @@ func (g *StateSizeGenerator) hasExistingMetrics() bool {
333319
return false
334320
}
335321

336-
var existed StateSizeMetrics
337-
if err := rlp.DecodeBytes(data, &existed); err != nil {
338-
log.Warn("Failed to decode existing state size metrics", "err", err)
322+
var existed stateSizeMetrics
323+
if err := json.Unmarshal(data, &existed); err != nil {
324+
log.Warn("Failed to decode existed state size metrics", "err", err)
339325
return false
340326
}
341327

342328
// Check if the existing metrics root matches our current root
343329
if (g.metrics.Root != common.Hash{}) && existed.Root != g.metrics.Root {
344-
log.Info("Existing state size metrics found but root mismatch", "existing", existed.Root, "current", g.metrics.Root)
330+
log.Info("Existing state size metrics found but root mismatch", "existed", existed.Root, "current", g.metrics.Root)
345331
return false
346332
}
347333

@@ -370,11 +356,11 @@ func (g *StateSizeGenerator) initializeMetrics() error {
370356

371357
// Metrics will be directly updated by each goroutine
372358
var (
373-
accountCount, accountBytes uint64
374-
storageCount, storageBytes uint64
375-
trieAccountNodeCount, trieAccountNodeBytes uint64
376-
trieStorageNodeCount, trieStorageNodeBytes uint64
377-
contractCount, contractBytes uint64
359+
accountCount, accountBytes int64
360+
storageCount, storageBytes int64
361+
trieAccountNodeCount, trieAccountNodeBytes int64
362+
trieStorageNodeCount, trieStorageNodeBytes int64
363+
contractCount, contractBytes int64
378364
)
379365

380366
// Start all table iterations concurrently with direct metric updates
@@ -428,7 +414,6 @@ func (g *StateSizeGenerator) initializeMetrics() error {
428414
return err
429415
}
430416

431-
// Update metrics (safe since we're in the single writer goroutine)
432417
g.metrics.AccountCount = accountCount
433418
g.metrics.AccountBytes = accountBytes
434419
g.metrics.StorageCount = storageCount
@@ -445,17 +430,17 @@ func (g *StateSizeGenerator) initializeMetrics() error {
445430
}
446431

447432
// iterateTable performs iteration over a specific table and returns the results
448-
func (g *StateSizeGenerator) iterateTable(ctx context.Context, prefix []byte, name string) (uint64, uint64, error) {
433+
func (g *StateSizeGenerator) iterateTable(ctx context.Context, prefix []byte, name string) (int64, int64, error) {
449434
log.Info("Iterating over state size", "table", name)
450435
start := time.Now()
451436

452-
var count, bytes uint64
437+
var count, bytes int64
453438
iter := g.db.NewIterator(prefix, nil)
454439
defer iter.Release()
455440

456441
for iter.Next() {
457442
count++
458-
bytes += uint64(len(iter.Key()) + len(iter.Value()))
443+
bytes += int64(len(iter.Key()) + len(iter.Value()))
459444

460445
// Check for cancellation periodically for performance
461446
if count%10000 == 0 {
@@ -480,19 +465,20 @@ func (g *StateSizeGenerator) iterateTable(ctx context.Context, prefix []byte, na
480465
}
481466

482467
func (g *StateSizeGenerator) updateMetrics() {
483-
accountCountGauge.Update(int64(g.metrics.AccountCount))
484-
accountBytesGauge.Update(int64(g.metrics.AccountBytes))
485-
storageCountGauge.Update(int64(g.metrics.StorageCount))
486-
storageBytesGauge.Update(int64(g.metrics.StorageBytes))
487-
trienodeCountGauge.Update(int64(g.metrics.TrieNodeCount))
488-
trienodeBytesGauge.Update(int64(g.metrics.TrieNodeBytes))
489-
contractCountGauge.Update(int64(g.metrics.ContractCount))
490-
contractBytesGauge.Update(int64(g.metrics.ContractBytes))
468+
accountCountGauge.Update(g.metrics.AccountCount)
469+
accountBytesGauge.Update(g.metrics.AccountBytes)
470+
storageCountGauge.Update(g.metrics.StorageCount)
471+
storageBytesGauge.Update(g.metrics.StorageBytes)
472+
trienodeCountGauge.Update(g.metrics.TrieNodeCount)
473+
trienodeBytesGauge.Update(g.metrics.TrieNodeBytes)
474+
contractCountGauge.Update(g.metrics.ContractCount)
475+
contractBytesGauge.Update(g.metrics.ContractBytes)
491476
}
492477

493478
// persistMetrics saves the current metrics to the database
494479
func (g *StateSizeGenerator) persistMetrics() {
495-
data, err := rlp.EncodeToBytes(*g.metrics)
480+
// RLP doesn't support int64, so we use JSON for simplicity
481+
data, err := json.Marshal(*g.metrics)
496482
if err != nil {
497483
log.Error("Failed to encode state size metrics", "err", err)
498484
return

0 commit comments

Comments
 (0)