From 3a71bf0e8e00ede8ebaf2e339159a272bd8b2814 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:19:36 -0600 Subject: [PATCH 1/3] Add tests for register reads for GetDomainStorageMap() This commit adds tests for register reads from GetStorageMap() for account storage format v1 and v2. --- runtime/storage_test.go | 968 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 968 insertions(+) diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 4e4dc261b..c0c8c0d3f 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -23,12 +23,14 @@ import ( "encoding/hex" "fmt" "math/rand" + "runtime" "slices" "sort" "strconv" "strings" "testing" + "github.com/fxamacker/cbor/v2" "github.com/onflow/atree" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -8081,6 +8083,940 @@ func TestDomainRegisterMigrationForLargeAccount(t *testing.T) { checkAccountStorageMapData(t, ledger.StoredValues, ledger.StorageIndices, address, accountValues) } +func TestGetDomainStorageMapRegisterReadsForNewAccount(t *testing.T) { + t.Parallel() + + address := common.MustBytesToAddress([]byte{0x1}) + + testCases := []struct { + name string + storageFormatV2Enabled bool + domain common.StorageDomain + createIfNotExists bool + expectedDomainStorageMapIsNil bool + expectedReadsFor1stGetDomainStorageMapCall []ownerKeyPair + expectedReadsFor2ndGetDomainStorageMapCall []ownerKeyPair + expectedReadsSet map[string]struct{} + }{ + // Test cases with storageFormatV2Enabled = false + { + name: "storageFormatV2Enabled = false, domain storage map does not exist, createIfNotExists = false", + storageFormatV2Enabled: false, + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: true, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = false, domain storage map does not exist, createIfNotExists = true", + storageFormatV2Enabled: false, + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reads from the second GetDomainStorageMap() because + // domain storage map is created and cached in the first GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + }, + }, + // Test cases with storageFormatV2Enabled = true + { + name: "storageFormatV2Enabled = true, domain storage map does not exist, createIfNotExists = false", + storageFormatV2Enabled: true, + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: true, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read all available domain registers to check if it is a new account + // Read returns no value. + { + owner: address[:], + key: []byte(common.PathDomainStorage.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPrivate.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPublic.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainContract.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainInbox.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainCapabilityController.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainCapabilityControllerTag.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainPathCapability.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainAccountCapability.Identifier()), + }, + // Try to read account register to create account storage map + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // Second GetDomainStorageMap() get cached account format v2 (cached during first GetDomainStorageMap()). + + // Try to read account register to create account storage map + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainContract.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainInbox.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainCapabilityController.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainCapabilityControllerTag.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathCapability.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainAccountCapability.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = true, domain storage map does not exist, createIfNotExists = true", + storageFormatV2Enabled: true, + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Check all domain registers + { + owner: address[:], + key: []byte(common.PathDomainStorage.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPrivate.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPublic.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainContract.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainInbox.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainCapabilityController.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainCapabilityControllerTag.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainPathCapability.Identifier()), + }, + { + owner: address[:], + key: []byte(common.StorageDomainAccountCapability.Identifier()), + }, + // Read account register to load account storage map + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reads from the second GetDomainStorageMap() because + // domain storage map is created and cached in the first GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainContract.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainInbox.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainCapabilityController.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainCapabilityControllerTag.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathCapability.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainAccountCapability.Identifier(): {}, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + var ledgerReads []ownerKeyPair + ledgerReadsSet := make(map[string]struct{}) + + // Create empty storage + ledger := NewTestLedger( + func(owner, key, _ []byte) { + ledgerReads = append( + ledgerReads, + ownerKeyPair{ + owner: owner, + key: key, + }, + ) + ledgerReadsSet[string(owner)+"|"+string(key)] = struct{}{} + }, + nil) + + storage := NewStorage( + ledger, + nil, + StorageConfig{ + StorageFormatV2Enabled: tc.storageFormatV2Enabled, + }, + ) + + inter := NewTestInterpreterWithStorage(t, storage) + + domainStorageMap := storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor1stGetDomainStorageMapCall, ledgerReads) + + ledgerReads = ledgerReads[:0] + + // Call GetDomainStorageMap() again to test account status is cached and no register reading is needed. + + domainStorageMap = storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor2ndGetDomainStorageMapCall, ledgerReads) + + // Check underlying ledger reads + require.Equal(t, len(ledgerReadsSet), len(tc.expectedReadsSet)) + for k := range ledgerReadsSet { + require.Contains(t, tc.expectedReadsSet, k) + } + }) + } +} + +func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { + + t.Parallel() + + address := common.MustBytesToAddress([]byte{0x1}) + + type getStorageDataFunc func() (storedValues map[string][]byte, StorageIndices map[string]uint64) + + createV1AccountWithDomain := func( + address common.Address, + domain common.StorageDomain, + ) getStorageDataFunc { + return func() (storedValues map[string][]byte, StorageIndices map[string]uint64) { + ledger := NewTestLedger(nil, nil) + + persistentSlabStorage := newSlabStorage(ledger) + + orderedMap, err := atree.NewMap( + persistentSlabStorage, + atree.Address(address), + atree.NewDefaultDigesterBuilder(), + interpreter.EmptyTypeInfo{}, + ) + require.NoError(t, err) + + slabIndex := orderedMap.SlabID().Index() + + for i := range 3 { + + key := interpreter.StringStorageMapKey(strconv.Itoa(i)) + + value := interpreter.NewUnmeteredIntValueFromInt64(int64(i)) + + existingStorable, err := orderedMap.Set( + key.AtreeValueCompare, + key.AtreeValueHashInput, + key.AtreeValue(), + value, + ) + require.NoError(t, err) + require.Nil(t, existingStorable) + } + + // Commit domain storage map + err = persistentSlabStorage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + // Create domain register + err = ledger.SetValue(address[:], []byte(domain.Identifier()), slabIndex[:]) + require.NoError(t, err) + + return ledger.StoredValues, ledger.StorageIndices + } + } + + testCases := []struct { + name string + getStorageData getStorageDataFunc + storageFormatV2Enabled bool + domain common.StorageDomain + createIfNotExists bool + expectedDomainStorageMapIsNil bool + expectedReadsFor1stGetDomainStorageMapCall []ownerKeyPair + expectedReadsFor2ndGetDomainStorageMapCall []ownerKeyPair + expectedReadsSet map[string]struct{} + }{ + // Test cases with storageFormatV2Enabled = false + { + name: "storageFormatV2Enabled = false, domain storage map does not exist, createIfNotExists = false", + storageFormatV2Enabled: false, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: true, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = false, domain storage map does not exist, createIfNotExists = true", + storageFormatV2Enabled: false, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading in second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(0). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = false, domain storage map exists, createIfNotExists = false", + storageFormatV2Enabled: false, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read domain storage map register + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading in second GetDomainStorageMap() because + // domain storage map is loaded and cached in the first + // GetDomainStorageMap(0). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + { + name: "storageFormatV2Enabled = false, domain storage map exists, createIfNotExists = true", + storageFormatV2Enabled: false, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read domain storage map register + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading in second GetDomainStorageMap() because + // domain storage map is loaded and cached in the first + // GetDomainStorageMap(0). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + // Test cases with storageFormatV2Enabled = true + { + name: "storageFormatV2Enabled = true, domain storage map does not exist, createIfNotExists = false", + storageFormatV2Enabled: true, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: true, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Check all domain registers until existing domain register is read + { + owner: address[:], + key: []byte(common.PathDomainStorage.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPrivate.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPublic.Identifier()), + }, + // Read requested domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // Read requested domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = true, domain storage map does not exist, createIfNotExists = true", + storageFormatV2Enabled: true, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Check all domain registers until existing domain register is read + { + owner: address[:], + key: []byte(common.PathDomainStorage.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPrivate.Identifier()), + }, + { + owner: address[:], + key: []byte(common.PathDomainPublic.Identifier()), + }, + // Read requested domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, + string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + }, + }, + { + name: "storageFormatV2Enabled = true, domain storage map exists, createIfNotExists = false", + storageFormatV2Enabled: true, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Check domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read domain storage map register + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + { + name: "storageFormatV2Enabled = true, domain storage map exists, createIfNotExists = true", + storageFormatV2Enabled: true, + getStorageData: createV1AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Check given domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read given domain register + { + owner: address[:], + key: []byte(common.StorageDomainPathStorage.Identifier()), + }, + // Read domain storage map register + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + storedValues, storedIndices := tc.getStorageData() + + var ledgerReads []ownerKeyPair + ledgerReadsSet := make(map[string]struct{}) + + ledger := NewTestLedgerWithData( + func(owner, key, _ []byte) { + ledgerReads = append( + ledgerReads, + ownerKeyPair{ + owner: owner, + key: key, + }, + ) + ledgerReadsSet[string(owner)+"|"+string(key)] = struct{}{} + }, + nil, + storedValues, + storedIndices, + ) + + storage := NewStorage( + ledger, + nil, + StorageConfig{ + StorageFormatV2Enabled: tc.storageFormatV2Enabled, + }, + ) + + inter := NewTestInterpreterWithStorage(t, storage) + + domainStorageMap := storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor1stGetDomainStorageMapCall, ledgerReads) + + ledgerReads = ledgerReads[:0] + + domainStorageMap = storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor2ndGetDomainStorageMapCall, ledgerReads) + + // Check underlying ledger reads + require.Equal(t, len(ledgerReadsSet), len(tc.expectedReadsSet)) + for k := range ledgerReadsSet { + require.Contains(t, tc.expectedReadsSet, k) + } + }) + } +} + +func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { + t.Parallel() + + address := common.MustBytesToAddress([]byte{0x1}) + + type getStorageDataFunc func() (storedValues map[string][]byte, StorageIndices map[string]uint64) + + createV2AccountWithDomain := func( + address common.Address, + domain common.StorageDomain, + ) getStorageDataFunc { + return func() (storedValues map[string][]byte, StorageIndices map[string]uint64) { + ledger := NewTestLedger(nil, nil) + + persistentSlabStorage := newSlabStorage(ledger) + + accountOrderedMap, err := atree.NewMap( + persistentSlabStorage, + atree.Address(address), + atree.NewDefaultDigesterBuilder(), + interpreter.EmptyTypeInfo{}, + ) + require.NoError(t, err) + + slabIndex := accountOrderedMap.SlabID().Index() + + domainOrderedMap, err := atree.NewMap( + persistentSlabStorage, + atree.Address(address), + atree.NewDefaultDigesterBuilder(), + interpreter.EmptyTypeInfo{}, + ) + require.NoError(t, err) + + domainKey := interpreter.Uint64StorageMapKey(domain) + + existingDomain, err := accountOrderedMap.Set( + domainKey.AtreeValueCompare, + domainKey.AtreeValueHashInput, + domainKey.AtreeValue(), + domainOrderedMap, + ) + require.NoError(t, err) + require.Nil(t, existingDomain) + + for i := range 3 { + + key := interpreter.StringStorageMapKey(strconv.Itoa(i)) + + value := interpreter.NewUnmeteredIntValueFromInt64(int64(i)) + + existingStorable, err := domainOrderedMap.Set( + key.AtreeValueCompare, + key.AtreeValueHashInput, + key.AtreeValue(), + value, + ) + require.NoError(t, err) + require.Nil(t, existingStorable) + } + + // Commit domain storage map + err = persistentSlabStorage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + // Create account register + err = ledger.SetValue(address[:], []byte(AccountStorageKey), slabIndex[:]) + require.NoError(t, err) + + return ledger.StoredValues, ledger.StorageIndices + } + } + + testCases := []struct { + name string + getStorageData getStorageDataFunc + domain common.StorageDomain + createIfNotExists bool + expectedDomainStorageMapIsNil bool + expectedReadsFor1stGetDomainStorageMapCall []ownerKeyPair + expectedReadsFor2ndGetDomainStorageMapCall []ownerKeyPair + expectedReadsSet map[string]struct{} + }{ + { + name: "domain storage map does not exist, createIfNotExists = false", + getStorageData: createV2AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: true, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account register + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account storage map + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap because + // account storage map is loaded and cached from first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + { + name: "domain storage map does not exist, createIfNotExists = true", + getStorageData: createV2AccountWithDomain(address, common.StorageDomainPathPublic), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account register + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account storage map + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + { + name: "domain storage map exists, createIfNotExists = false", + getStorageData: createV2AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: false, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account register + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account storage map + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + { + name: "domain storage map exists, createIfNotExists = true", + getStorageData: createV2AccountWithDomain(address, common.StorageDomainPathStorage), + domain: common.StorageDomainPathStorage, + createIfNotExists: true, + expectedDomainStorageMapIsNil: false, + expectedReadsFor1stGetDomainStorageMapCall: []ownerKeyPair{ + // Check if account is v2 + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account register + { + owner: address[:], + key: []byte(AccountStorageKey), + }, + // Read account storage map + { + owner: address[:], + key: []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}, + }, + }, + expectedReadsFor2ndGetDomainStorageMapCall: []ownerKeyPair{ + // No register reading from second GetDomainStorageMap() because + // domain storage map is created and cached in the first + // GetDomainStorageMap(). + }, + expectedReadsSet: map[string]struct{}{ + string(address[:]) + "|" + AccountStorageKey: {}, + string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + storedValues, storedIndices := tc.getStorageData() + + var ledgerReads []ownerKeyPair + ledgerReadsSet := make(map[string]struct{}) + + ledger := NewTestLedgerWithData( + func(owner, key, _ []byte) { + ledgerReads = append( + ledgerReads, + ownerKeyPair{ + owner: owner, + key: key, + }, + ) + ledgerReadsSet[string(owner)+"|"+string(key)] = struct{}{} + }, + nil, + storedValues, + storedIndices, + ) + + storage := NewStorage( + ledger, + nil, + StorageConfig{ + StorageFormatV2Enabled: true, + }, + ) + + inter := NewTestInterpreterWithStorage(t, storage) + + domainStorageMap := storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor1stGetDomainStorageMapCall, ledgerReads) + + ledgerReads = ledgerReads[:0] + + domainStorageMap = storage.GetDomainStorageMap(inter, address, tc.domain, tc.createIfNotExists) + require.Equal(t, tc.expectedDomainStorageMapIsNil, domainStorageMap == nil) + require.Equal(t, tc.expectedReadsFor2ndGetDomainStorageMapCall, ledgerReads) + + // Check underlying ledger reads + require.Equal(t, len(ledgerReadsSet), len(tc.expectedReadsSet)) + for k := range ledgerReadsSet { + require.Contains(t, tc.expectedReadsSet, k) + } + }) + } +} + // createAndWriteAccountStorageMap creates account storage map with given domains and writes random values to domain storage map. func createAndWriteAccountStorageMap( t testing.TB, @@ -8207,3 +9143,35 @@ func checkAccountStorageMapData( require.Equal(tb, 1, len(rootSlabIDs)) require.Contains(tb, rootSlabIDs, accountSlabID) } + +func newSlabStorage(ledger atree.Ledger) *atree.PersistentSlabStorage { + decodeStorable := func( + decoder *cbor.StreamDecoder, + slabID atree.SlabID, + inlinedExtraData []atree.ExtraData, + ) ( + atree.Storable, + error, + ) { + return interpreter.DecodeStorable( + decoder, + slabID, + inlinedExtraData, + nil, + ) + } + + decodeTypeInfo := func(decoder *cbor.StreamDecoder) (atree.TypeInfo, error) { + return interpreter.DecodeTypeInfo(decoder, nil) + } + + ledgerStorage := atree.NewLedgerBaseStorage(ledger) + + return atree.NewPersistentSlabStorage( + ledgerStorage, + interpreter.CBOREncMode, + interpreter.CBORDecMode, + decodeStorable, + decodeTypeInfo, + ) +} From 7772eb085ca44dd60c194b21762b126939356fde Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:51:27 -0600 Subject: [PATCH 2/3] Add test helper function --- runtime/storage_test.go | 114 ++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 50 deletions(-) diff --git a/runtime/storage_test.go b/runtime/storage_test.go index c0c8c0d3f..d1e24cfd9 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -8120,7 +8120,7 @@ func TestGetDomainStorageMapRegisterReadsForNewAccount(t *testing.T) { }, }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, }, }, { @@ -8141,7 +8141,7 @@ func TestGetDomainStorageMapRegisterReadsForNewAccount(t *testing.T) { // domain storage map is created and cached in the first GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, }, }, // Test cases with storageFormatV2Enabled = true @@ -8211,16 +8211,16 @@ func TestGetDomainStorageMapRegisterReadsForNewAccount(t *testing.T) { }, }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainContract.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainInbox.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainCapabilityController.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainCapabilityControllerTag.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathCapability.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainAccountCapability.Identifier(): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPrivate): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPublic): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainContract): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainInbox): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainCapabilityController): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainCapabilityControllerTag): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathCapability): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainAccountCapability): {}, }, }, { @@ -8283,16 +8283,16 @@ func TestGetDomainStorageMapRegisterReadsForNewAccount(t *testing.T) { // domain storage map is created and cached in the first GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainContract.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainInbox.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainCapabilityController.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainCapabilityControllerTag.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathCapability.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainAccountCapability.Identifier(): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPrivate): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPublic): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainContract): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainInbox): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainCapabilityController): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainCapabilityControllerTag): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathCapability): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainAccountCapability): {}, }, }, } @@ -8437,7 +8437,7 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { }, }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, }, }, { @@ -8460,7 +8460,7 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(0). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, }, }, { @@ -8488,8 +8488,8 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(0). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, { @@ -8517,8 +8517,8 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(0). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, // Test cases with storageFormatV2Enabled = true @@ -8562,10 +8562,10 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { }, }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPrivate): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPublic): {}, }, }, { @@ -8606,10 +8606,10 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPrivate.Identifier(): {}, - string(address[:]) + "|" + common.StorageDomainPathPublic.Identifier(): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPrivate): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathPublic): {}, }, }, { @@ -8647,9 +8647,9 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, { @@ -8687,9 +8687,9 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + common.StorageDomainPathStorage.Identifier(): {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndDomain(address, common.StorageDomainPathStorage): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, } @@ -8859,8 +8859,8 @@ func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, { @@ -8892,8 +8892,8 @@ func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, { @@ -8925,8 +8925,8 @@ func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, { @@ -8958,8 +8958,8 @@ func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { // GetDomainStorageMap(). }, expectedReadsSet: map[string]struct{}{ - string(address[:]) + "|" + AccountStorageKey: {}, - string(address[:]) + "|" + string([]byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, + concatRegisterAddressAndKey(address, []byte(AccountStorageKey)): {}, + concatRegisterAddressAndKey(address, []byte{'$', 0, 0, 0, 0, 0, 0, 0, 1}): {}, }, }, } @@ -9175,3 +9175,17 @@ func newSlabStorage(ledger atree.Ledger) *atree.PersistentSlabStorage { decodeTypeInfo, ) } + +func concatRegisterAddressAndKey( + address common.Address, + key []byte, +) string { + return string(address[:]) + "|" + string(key) +} + +func concatRegisterAddressAndDomain( + address common.Address, + domain common.StorageDomain, +) string { + return string(address[:]) + "|" + domain.Identifier() +} From ba76c1111ddc6f985953c2d56f969a528abdf905 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:59:00 -0600 Subject: [PATCH 3/3] Extract new function NewPersistentSlabStorage() --- runtime/storage.go | 16 ++++++++++++---- runtime/storage_test.go | 37 ++----------------------------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/runtime/storage.go b/runtime/storage.go index 8198e69fa..49aaa92b4 100644 --- a/runtime/storage.go +++ b/runtime/storage.go @@ -69,11 +69,10 @@ type Storage struct { var _ atree.SlabStorage = &Storage{} var _ interpreter.Storage = &Storage{} -func NewStorage( +func NewPersistentSlabStorage( ledger atree.Ledger, memoryGauge common.MemoryGauge, - config StorageConfig, -) *Storage { +) *atree.PersistentSlabStorage { decodeStorable := func( decoder *cbor.StreamDecoder, slabID atree.SlabID, @@ -95,13 +94,22 @@ func NewStorage( } ledgerStorage := atree.NewLedgerBaseStorage(ledger) - persistentSlabStorage := atree.NewPersistentSlabStorage( + + return atree.NewPersistentSlabStorage( ledgerStorage, interpreter.CBOREncMode, interpreter.CBORDecMode, decodeStorable, decodeTypeInfo, ) +} + +func NewStorage( + ledger atree.Ledger, + memoryGauge common.MemoryGauge, + config StorageConfig, +) *Storage { + persistentSlabStorage := NewPersistentSlabStorage(ledger, memoryGauge) accountStorageV1 := NewAccountStorageV1( ledger, diff --git a/runtime/storage_test.go b/runtime/storage_test.go index d1e24cfd9..f0bbaef75 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -30,7 +30,6 @@ import ( "strings" "testing" - "github.com/fxamacker/cbor/v2" "github.com/onflow/atree" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -8363,7 +8362,7 @@ func TestGetDomainStorageMapRegisterReadsForV1Account(t *testing.T) { return func() (storedValues map[string][]byte, StorageIndices map[string]uint64) { ledger := NewTestLedger(nil, nil) - persistentSlabStorage := newSlabStorage(ledger) + persistentSlabStorage := NewPersistentSlabStorage(ledger, nil) orderedMap, err := atree.NewMap( persistentSlabStorage, @@ -8761,7 +8760,7 @@ func TestGetDomainStorageMapRegisterReadsForV2Account(t *testing.T) { return func() (storedValues map[string][]byte, StorageIndices map[string]uint64) { ledger := NewTestLedger(nil, nil) - persistentSlabStorage := newSlabStorage(ledger) + persistentSlabStorage := NewPersistentSlabStorage(ledger, nil) accountOrderedMap, err := atree.NewMap( persistentSlabStorage, @@ -9144,38 +9143,6 @@ func checkAccountStorageMapData( require.Contains(tb, rootSlabIDs, accountSlabID) } -func newSlabStorage(ledger atree.Ledger) *atree.PersistentSlabStorage { - decodeStorable := func( - decoder *cbor.StreamDecoder, - slabID atree.SlabID, - inlinedExtraData []atree.ExtraData, - ) ( - atree.Storable, - error, - ) { - return interpreter.DecodeStorable( - decoder, - slabID, - inlinedExtraData, - nil, - ) - } - - decodeTypeInfo := func(decoder *cbor.StreamDecoder) (atree.TypeInfo, error) { - return interpreter.DecodeTypeInfo(decoder, nil) - } - - ledgerStorage := atree.NewLedgerBaseStorage(ledger) - - return atree.NewPersistentSlabStorage( - ledgerStorage, - interpreter.CBOREncMode, - interpreter.CBORDecMode, - decodeStorable, - decodeTypeInfo, - ) -} - func concatRegisterAddressAndKey( address common.Address, key []byte,