@@ -49,7 +49,7 @@ type Storage struct {
49
49
50
50
// cachedV1Accounts contains the cached result of determining
51
51
// if the account is in storage format v1 or not.
52
- cachedV1Accounts * orderedmap. OrderedMap [common.Address , bool ]
52
+ cachedV1Accounts map [common.Address ] bool
53
53
54
54
// contractUpdates is a cache of contract updates.
55
55
// Key is StorageKey{contract_address, contract_name} and value is contract composite value.
@@ -61,8 +61,9 @@ type Storage struct {
61
61
62
62
Config StorageConfig
63
63
64
- AccountStorageV1 * AccountStorageV1
65
- AccountStorageV2 * AccountStorageV2
64
+ AccountStorageV1 * AccountStorageV1
65
+ AccountStorageV2 * AccountStorageV2
66
+ scheduledV2Migrations []common.Address
66
67
}
67
68
68
69
var _ atree.SlabStorage = & Storage {}
@@ -183,12 +184,8 @@ func (s *Storage) IsV1Account(address common.Address) (isV1 bool) {
183
184
184
185
// Check cache
185
186
186
- if s .cachedV1Accounts != nil {
187
- var present bool
188
- isV1 , present = s .cachedV1Accounts .Get (address )
189
- if present {
190
- return isV1
191
- }
187
+ if isV1 , present := s .cachedV1Accounts [address ]; present {
188
+ return isV1
192
189
}
193
190
194
191
// Cache result
@@ -230,9 +227,9 @@ func (s *Storage) IsV1Account(address common.Address) (isV1 bool) {
230
227
231
228
func (s * Storage ) cacheIsV1Account (address common.Address , isV1 bool ) {
232
229
if s .cachedV1Accounts == nil {
233
- s .cachedV1Accounts = & orderedmap. OrderedMap [common.Address , bool ] {}
230
+ s .cachedV1Accounts = map [common.Address ] bool {}
234
231
}
235
- s .cachedV1Accounts . Set ( address , isV1 )
232
+ s .cachedV1Accounts [ address ] = isV1
236
233
}
237
234
238
235
func (s * Storage ) cacheDomainStorageMap (
@@ -408,9 +405,23 @@ func (s *Storage) commit(inter *interpreter.Interpreter, commitContractUpdates b
408
405
}
409
406
}
410
407
408
+ func (s * Storage ) ScheduleV2Migration (address common.Address ) {
409
+ s .scheduledV2Migrations = append (s .scheduledV2Migrations , address )
410
+ }
411
+
412
+ func (s * Storage ) ScheduleV2MigrationForModifiedAccounts () {
413
+ for address , isV1 := range s .cachedV1Accounts { //nolint:maprange
414
+ if ! isV1 || ! s .PersistentSlabStorage .HasUnsavedChanges (atree .Address (address )) {
415
+ continue
416
+ }
417
+
418
+ s .ScheduleV2Migration (address )
419
+ }
420
+ }
421
+
411
422
func (s * Storage ) migrateV1AccountsToV2 (inter * interpreter.Interpreter ) error {
412
423
413
- if s . cachedV1Accounts == nil {
424
+ if len ( s . scheduledV2Migrations ) == 0 {
414
425
return nil
415
426
}
416
427
@@ -443,13 +454,18 @@ func (s *Storage) migrateV1AccountsToV2(inter *interpreter.Interpreter) error {
443
454
getDomainStorageMap ,
444
455
)
445
456
446
- for pair := s .cachedV1Accounts .Oldest (); pair != nil ; pair = pair .Next () {
447
- address := pair .Key
448
- isV1 := pair .Value
457
+ // Ensure the scheduled accounts are migrated in a deterministic order
449
458
450
- if ! isV1 || ! s .PersistentSlabStorage .HasUnsavedChanges (atree .Address (address )) {
451
- continue
452
- }
459
+ sort .Slice (
460
+ s .scheduledV2Migrations ,
461
+ func (i , j int ) bool {
462
+ address1 := s .scheduledV2Migrations [i ]
463
+ address2 := s .scheduledV2Migrations [j ]
464
+ return address1 .Compare (address2 ) < 0
465
+ },
466
+ )
467
+
468
+ for _ , address := range s .scheduledV2Migrations {
453
469
454
470
accountStorageMap , err := migrator .MigrateAccount (address )
455
471
if err != nil {
@@ -466,6 +482,8 @@ func (s *Storage) migrateV1AccountsToV2(inter *interpreter.Interpreter) error {
466
482
s .cacheIsV1Account (address , false )
467
483
}
468
484
485
+ s .scheduledV2Migrations = nil
486
+
469
487
return nil
470
488
}
471
489
0 commit comments