Skip to content

Commit c2eacce

Browse files
committed
chore: self review
1 parent 71a6e74 commit c2eacce

6 files changed

Lines changed: 72 additions & 68 deletions

File tree

core/state/accessors.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ func HasContract(r db.KeyValueReader, addr *felt.Felt) (bool, error) {
4141
return r.Has(key)
4242
}
4343

44-
// WriteContract writes a Contract record from raw fields. Used by the running
45-
// node (via writeContract on a fully-built stateContract) and by the deprecated
46-
// → new state migration (with StorageRoot left zero — the new state lazily
47-
// backfills it on the contract's first storage write).
4844
func WriteContract(
4945
w db.KeyValueWriter,
5046
addr *felt.Felt,

migration/headstate/committer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func newCommitter(
3030
func (c *committer) Run(_ int, t task, _ chan<- struct{}) error {
3131
c.logger.Debug(
3232
"writing batch",
33-
zap.Int("addrCount", t.addrCount),
33+
zap.Int("completedAddrs", t.completedAddrs),
3434
zap.Int("batchSize", t.batch.Size()),
3535
)
3636

@@ -39,7 +39,7 @@ func (c *committer) Run(_ int, t task, _ chan<- struct{}) error {
3939
return err
4040
}
4141

42-
c.counter.log(byteSize, t.addrCount)
42+
c.counter.log(byteSize, t.completedAddrs)
4343
c.batchSemaphore.Put()
4444
return nil
4545
}

migration/headstate/counter.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import (
99
)
1010

1111
type counter struct {
12-
logger log.StructuredLogger
13-
timeLogRate time.Duration
14-
start time.Time
15-
size uint64
16-
addrCount uint64
12+
logger log.StructuredLogger
13+
timeLogRate time.Duration
14+
start time.Time
15+
size uint64
16+
completedAddrs uint64
1717
}
1818

1919
func newCounter(logger log.StructuredLogger, timeLogRate time.Duration) counter {
@@ -24,24 +24,24 @@ func newCounter(logger log.StructuredLogger, timeLogRate time.Duration) counter
2424
}
2525
}
2626

27-
func (c *counter) log(byteSize uint64, addrCount int) {
27+
func (c *counter) log(byteSize uint64, completedAddrs int) {
2828
c.size += byteSize
29-
c.addrCount += uint64(addrCount)
29+
c.completedAddrs += uint64(completedAddrs)
3030

3131
now := time.Now()
3232
elapsed := now.Sub(c.start).Seconds()
33-
if elapsed > float64(c.timeLogRate.Seconds()) {
33+
if elapsed > c.timeLogRate.Seconds() {
3434
mbs := float64(c.size) / float64(db.Megabyte)
3535
c.logger.Info(
3636
"write speed",
3737
zap.Float64("MB", mbs),
3838
zap.Float64("MB/s", mbs/elapsed),
39-
zap.Uint64("contracts", c.addrCount),
40-
zap.Float64("contracts/s", float64(c.addrCount)/elapsed),
39+
zap.Uint64("completedContracts", c.completedAddrs),
40+
zap.Float64("completedContracts/s", float64(c.completedAddrs)/elapsed),
4141
zap.Float64("time", elapsed),
4242
)
4343
c.start = now
4444
c.size = 0
45-
c.addrCount = 0
45+
c.completedAddrs = 0
4646
}
4747
}

migration/headstate/ingestor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ func (c *ingestor) Run(index int, addr felt.Address, outputs chan<- task) error
4343
return err
4444
}
4545
if t.batch.Size() > sizeBefore {
46-
t.addrCount++
46+
t.completedAddrs++
4747
}
4848

4949
if t.batch.Size() >= targetBatchByteSize {
50-
outputs <- task{batch: t.batch, addrCount: t.addrCount}
51-
t.addrCount = 0
50+
outputs <- task{batch: t.batch, completedAddrs: t.completedAddrs}
51+
t.completedAddrs = 0
5252
t.batch = c.batchSemaphore.GetBlocking()
5353
}
5454
return nil

migration/headstate/migrator.go

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package headstate
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"iter"
78
"time"
@@ -24,15 +25,67 @@ const (
2425
)
2526

2627
type task struct {
27-
batch db.Batch
28-
addrCount int
28+
batch db.Batch
29+
completedAddrs int
2930
}
3031

3132
var (
3233
shouldRerun = []byte{}
3334
shouldNotRerun = []byte(nil)
3435
)
3536

37+
var _ migration.Migration = (*Migrator)(nil)
38+
39+
// Migrator consolidates the deprecated per-field contract layout into a
40+
// single Contract record per address, written via state.WriteContract:
41+
//
42+
// ContractClassHash[addr]
43+
// ContractNonce[addr]
44+
// ContractDeploymentHeight[addr]
45+
// │
46+
// ▼
47+
// Contract[addr] = { ClassHash, Nonce, DeployedHeight }
48+
//
49+
// StorageRoot is left zero — the running node lazily backfills it on the
50+
// contract's first storage write.
51+
//
52+
// Each address discovered in the ContractClassHash bucket is processed by one
53+
// of ingestorCount worker goroutines that read the three old fields into a
54+
// shared db.Batch; a single committer drains batches to disk. Once every
55+
// address has been migrated, the three deprecated buckets are wiped via
56+
// DeleteRange.
57+
//
58+
// Re-run safe: an address whose Contract record already exists is skipped
59+
// (via state.HasContract), and the trailing wipe re-issues DeleteRange over
60+
// the (possibly already empty) ranges.
61+
type Migrator struct{}
62+
63+
func (Migrator) Before([]byte) error {
64+
return nil
65+
}
66+
67+
func (Migrator) Migrate(
68+
ctx context.Context,
69+
database db.KeyValueStore,
70+
_ *networks.Network,
71+
logger log.StructuredLogger,
72+
) ([]byte, error) {
73+
addressesIter, sourceErr := pendingAddresses(database)
74+
res := migrateAddresses(ctx, database, logger, addressesIter)
75+
76+
if err := errors.Join(sourceErr(), res.Err); err != nil {
77+
return shouldRerun, err
78+
}
79+
if !res.IsDone {
80+
if ctxErr := ctx.Err(); ctxErr != nil {
81+
return shouldRerun, ctxErr
82+
}
83+
return shouldRerun, errors.New("headstate migration did not complete")
84+
}
85+
86+
return shouldNotRerun, wipeDeprecatedBuckets(database)
87+
}
88+
3689
func migrateAddresses(
3790
ctx context.Context,
3891
database db.KeyValueStore,
@@ -64,51 +117,6 @@ func migrateAddresses(
64117
return wait()
65118
}
66119

67-
var _ migration.Migration = (*Migrator)(nil)
68-
69-
type Migrator struct{}
70-
71-
func (Migrator) Before([]byte) error {
72-
return nil
73-
}
74-
75-
func (Migrator) Migrate(
76-
ctx context.Context,
77-
database db.KeyValueStore,
78-
_ *networks.Network,
79-
logger log.StructuredLogger,
80-
) ([]byte, error) {
81-
hasPending, err := hasPendingAddresses(database)
82-
if err != nil {
83-
return shouldRerun, err
84-
}
85-
if !hasPending {
86-
return shouldNotRerun, wipeDeprecatedBuckets(database)
87-
}
88-
89-
addressesIter, sourceErr := pendingAddresses(database)
90-
res := migrateAddresses(ctx, database, logger, addressesIter)
91-
92-
if err := sourceErr(); err != nil {
93-
return shouldRerun, err
94-
}
95-
if res.Err != nil || !res.IsDone {
96-
return shouldRerun, res.Err
97-
}
98-
99-
return shouldNotRerun, wipeDeprecatedBuckets(database)
100-
}
101-
102-
func hasPendingAddresses(r db.KeyValueReader) (bool, error) {
103-
prefix := db.ContractClassHash.Key()
104-
it, err := r.NewIterator(prefix, true)
105-
if err != nil {
106-
return false, err
107-
}
108-
defer it.Close()
109-
return it.First(), nil
110-
}
111-
112120
func pendingAddresses(r db.KeyValueReader) (iter.Seq[felt.Address], func() error) {
113121
var iterErr error
114122
seq := func(yield func(felt.Address) bool) {

migration/headstate/migrator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func TestMigrate_Idempotent(t *testing.T) {
189189
}
190190
seedDeprecated(t, memDB, seeds)
191191

192-
for i := 0; i < 3; i++ {
192+
for i := range 3 {
193193
res, err := headstate.Migrator{}.Migrate(
194194
context.Background(),
195195
memDB,

0 commit comments

Comments
 (0)