Skip to content

Commit d3c76d5

Browse files
committed
allow scheduling migrations of accounts to V2
1 parent 16130ed commit d3c76d5

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

Diff for: common/address.go

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package common
2020

2121
import (
22+
"bytes"
2223
"encoding/hex"
2324
goErrors "errors"
2425
"fmt"
@@ -112,6 +113,10 @@ func (a Address) HexWithPrefix() string {
112113
return fmt.Sprintf("0x%x", [AddressLength]byte(a))
113114
}
114115

116+
func (a Address) Compare(other Address) int {
117+
return bytes.Compare(a[:], other[:])
118+
}
119+
115120
// HexToAddress converts a hex string to an Address after
116121
// ensuring that the hex string starts with the prefix 0x.
117122
func HexToAddressAssertPrefix(h string) (Address, error) {

Diff for: runtime/storage.go

+36-18
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type Storage struct {
4949

5050
// cachedV1Accounts contains the cached result of determining
5151
// if the account is in storage format v1 or not.
52-
cachedV1Accounts *orderedmap.OrderedMap[common.Address, bool]
52+
cachedV1Accounts map[common.Address]bool
5353

5454
// contractUpdates is a cache of contract updates.
5555
// Key is StorageKey{contract_address, contract_name} and value is contract composite value.
@@ -61,8 +61,9 @@ type Storage struct {
6161

6262
Config StorageConfig
6363

64-
AccountStorageV1 *AccountStorageV1
65-
AccountStorageV2 *AccountStorageV2
64+
AccountStorageV1 *AccountStorageV1
65+
AccountStorageV2 *AccountStorageV2
66+
scheduledV2Migrations []common.Address
6667
}
6768

6869
var _ atree.SlabStorage = &Storage{}
@@ -183,12 +184,8 @@ func (s *Storage) IsV1Account(address common.Address) (isV1 bool) {
183184

184185
// Check cache
185186

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
192189
}
193190

194191
// Cache result
@@ -230,9 +227,9 @@ func (s *Storage) IsV1Account(address common.Address) (isV1 bool) {
230227

231228
func (s *Storage) cacheIsV1Account(address common.Address, isV1 bool) {
232229
if s.cachedV1Accounts == nil {
233-
s.cachedV1Accounts = &orderedmap.OrderedMap[common.Address, bool]{}
230+
s.cachedV1Accounts = map[common.Address]bool{}
234231
}
235-
s.cachedV1Accounts.Set(address, isV1)
232+
s.cachedV1Accounts[address] = isV1
236233
}
237234

238235
func (s *Storage) cacheDomainStorageMap(
@@ -408,9 +405,23 @@ func (s *Storage) commit(inter *interpreter.Interpreter, commitContractUpdates b
408405
}
409406
}
410407

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+
411422
func (s *Storage) migrateV1AccountsToV2(inter *interpreter.Interpreter) error {
412423

413-
if s.cachedV1Accounts == nil {
424+
if len(s.scheduledV2Migrations) == 0 {
414425
return nil
415426
}
416427

@@ -443,13 +454,18 @@ func (s *Storage) migrateV1AccountsToV2(inter *interpreter.Interpreter) error {
443454
getDomainStorageMap,
444455
)
445456

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
449458

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 {
453469

454470
accountStorageMap, err := migrator.MigrateAccount(address)
455471
if err != nil {
@@ -466,6 +482,8 @@ func (s *Storage) migrateV1AccountsToV2(inter *interpreter.Interpreter) error {
466482
s.cacheIsV1Account(address, false)
467483
}
468484

485+
s.scheduledV2Migrations = nil
486+
469487
return nil
470488
}
471489

Diff for: runtime/storage_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -7181,6 +7181,8 @@ func TestRuntimeStorageForUnmigratedAccount(t *testing.T) {
71817181
domainStorageMap := storage.GetDomainStorageMap(inter, address, nonExistingDomain, createIfNotExists)
71827182
require.Nil(t, domainStorageMap)
71837183

7184+
storage.ScheduleV2MigrationForModifiedAccounts()
7185+
71847186
// Commit changes
71857187
const commitContractUpdates = false
71867188
err := storage.Commit(inter, commitContractUpdates)
@@ -7335,6 +7337,9 @@ func TestRuntimeStorageForUnmigratedAccount(t *testing.T) {
73357337
accountValues[domain] = writeToDomainStorageMap(inter, domainStorageMap, tc.newDomainStorageMapCount, random)
73367338
}
73377339

7340+
// TODO:
7341+
storage.ScheduleV2MigrationForModifiedAccounts()
7342+
73387343
// Commit changes
73397344
const commitContractUpdates = false
73407345
err := storage.Commit(inter, commitContractUpdates)
@@ -7480,6 +7485,9 @@ func TestRuntimeStorageForUnmigratedAccount(t *testing.T) {
74807485
}
74817486
}
74827487

7488+
// TODO:
7489+
storage.ScheduleV2MigrationForModifiedAccounts()
7490+
74837491
// Commit changes
74847492
const commitContractUpdates = false
74857493
err := storage.Commit(inter, commitContractUpdates)
@@ -7610,6 +7618,9 @@ func TestRuntimeStorageForUnmigratedAccount(t *testing.T) {
76107618
}
76117619
}
76127620

7621+
// TODO:
7622+
storage.ScheduleV2MigrationForModifiedAccounts()
7623+
76137624
// Commit changes
76147625
const commitContractUpdates = false
76157626
err := storage.Commit(inter, commitContractUpdates)
@@ -8037,6 +8048,9 @@ func TestDomainRegisterMigrationForLargeAccount(t *testing.T) {
80378048

80388049
accountValues[domain] = make(domainStorageMapValues)
80398050

8051+
// TODO:
8052+
storage.ScheduleV2MigrationForModifiedAccounts()
8053+
80408054
// Commit changes
80418055
const commitContractUpdates = false
80428056
err := storage.Commit(inter, commitContractUpdates)

0 commit comments

Comments
 (0)