From 4fd610ac529be171c69c20ca024ef7e76af09d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 18 Nov 2024 14:01:52 -0800 Subject: [PATCH] refactor slab index register reading/writing to separate file and improve naming --- runtime/account_storage_v1.go | 4 +- runtime/account_storage_v2.go | 10 ++-- runtime/slabindex.go | 86 +++++++++++++++++++++++++++++++++++ runtime/storage.go | 61 +------------------------ 4 files changed, 94 insertions(+), 67 deletions(-) create mode 100644 runtime/slabindex.go diff --git a/runtime/account_storage_v1.go b/runtime/account_storage_v1.go index fe1419a35..53eec2fef 100644 --- a/runtime/account_storage_v1.go +++ b/runtime/account_storage_v1.go @@ -175,7 +175,7 @@ func (s *AccountStorageV1) writeStorageDomainSlabIndex( storageDomainKey interpreter.StorageDomainKey, slabIndex atree.SlabIndex, ) error { - return writeSlabIndex( + return writeSlabIndexToRegister( s.ledger, storageDomainKey.Address, []byte(storageDomainKey.Domain.Identifier()), @@ -191,7 +191,7 @@ func getDomainStorageMapFromV1DomainRegister( domain common.StorageDomain, ) (*interpreter.DomainStorageMap, error) { - domainStorageSlabIndex, domainRegisterExists, err := getSlabIndexFromRegisterValue( + domainStorageSlabIndex, domainRegisterExists, err := readSlabIndexFromRegister( ledger, address, []byte(domain.Identifier()), diff --git a/runtime/account_storage_v2.go b/runtime/account_storage_v2.go index 32619ac45..71e19fdae 100644 --- a/runtime/account_storage_v2.go +++ b/runtime/account_storage_v2.go @@ -238,7 +238,7 @@ func (s *AccountStorageV2) writeAccountStorageSlabIndex( address common.Address, slabIndex atree.SlabIndex, ) error { - return writeSlabIndex( + return writeSlabIndexToRegister( s.ledger, address, []byte(AccountStorageKey), @@ -246,7 +246,7 @@ func (s *AccountStorageV2) writeAccountStorageSlabIndex( ) } -func getAccountStorageSlabIndex( +func readAccountStorageSlabIndexFromRegister( ledger atree.Ledger, address common.Address, ) ( @@ -254,7 +254,7 @@ func getAccountStorageSlabIndex( bool, error, ) { - return getSlabIndexFromRegisterValue( + return readSlabIndexFromRegister( ledger, address, []byte(AccountStorageKey), @@ -269,7 +269,7 @@ func getAccountStorageMapFromRegister( *interpreter.AccountStorageMap, error, ) { - slabIndex, registerExists, err := getAccountStorageSlabIndex( + slabIndex, registerExists, err := readAccountStorageSlabIndexFromRegister( ledger, address, ) @@ -293,7 +293,7 @@ func hasAccountStorageMap( address common.Address, ) (bool, error) { - _, registerExists, err := getAccountStorageSlabIndex( + _, registerExists, err := readAccountStorageSlabIndexFromRegister( ledger, address, ) diff --git a/runtime/slabindex.go b/runtime/slabindex.go new file mode 100644 index 000000000..00178608d --- /dev/null +++ b/runtime/slabindex.go @@ -0,0 +1,86 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Flow Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package runtime + +import ( + "github.com/onflow/atree" + + "github.com/onflow/cadence/common" + "github.com/onflow/cadence/errors" + "github.com/onflow/cadence/interpreter" +) + +// readSlabIndexFromRegister returns register value as atree.SlabIndex. +// This function returns error if +// - underlying ledger panics, or +// - underlying ledger returns error when retrieving ledger value, or +// - retrieved ledger value is invalid (for atree.SlabIndex). +func readSlabIndexFromRegister( + ledger atree.Ledger, + address common.Address, + key []byte, +) (atree.SlabIndex, bool, error) { + var data []byte + var err error + errors.WrapPanic(func() { + data, err = ledger.GetValue(address[:], key) + }) + if err != nil { + return atree.SlabIndex{}, false, interpreter.WrappedExternalError(err) + } + + dataLength := len(data) + + if dataLength == 0 { + return atree.SlabIndex{}, false, nil + } + + isStorageIndex := dataLength == storageIndexLength + if !isStorageIndex { + // Invalid data in register + + // TODO: add dedicated error type? + return atree.SlabIndex{}, false, errors.NewUnexpectedError( + "invalid storage index for storage map of account '%x': expected length %d, got %d", + address[:], storageIndexLength, dataLength, + ) + } + + return atree.SlabIndex(data), true, nil +} + +func writeSlabIndexToRegister( + ledger atree.Ledger, + address common.Address, + key []byte, + slabIndex atree.SlabIndex, +) error { + var err error + errors.WrapPanic(func() { + err = ledger.SetValue( + address[:], + key, + slabIndex[:], + ) + }) + if err != nil { + return interpreter.WrappedExternalError(err) + } + return nil +} diff --git a/runtime/storage.go b/runtime/storage.go index 1ca3906dc..8198e69fa 100644 --- a/runtime/storage.go +++ b/runtime/storage.go @@ -213,7 +213,7 @@ func (s *Storage) IsV1Account(address common.Address) (isV1 bool) { // Check if a storage map register exists for any of the domains. // Check the most frequently used domains first, such as storage, public, private. for _, domain := range common.AllStorageDomains { - _, domainExists, err := getSlabIndexFromRegisterValue( + _, domainExists, err := readSlabIndexFromRegister( s.Ledger, address, []byte(domain.Identifier()), @@ -247,45 +247,6 @@ func (s *Storage) cacheDomainStorageMap( s.cachedDomainStorageMaps[storageDomainKey] = domainStorageMap } -// getSlabIndexFromRegisterValue returns register value as atree.SlabIndex. -// This function returns error if -// - underlying ledger panics, or -// - underlying ledger returns error when retrieving ledger value, or -// - retrieved ledger value is invalid (for atree.SlabIndex). -func getSlabIndexFromRegisterValue( - ledger atree.Ledger, - address common.Address, - key []byte, -) (atree.SlabIndex, bool, error) { - var data []byte - var err error - errors.WrapPanic(func() { - data, err = ledger.GetValue(address[:], key) - }) - if err != nil { - return atree.SlabIndex{}, false, interpreter.WrappedExternalError(err) - } - - dataLength := len(data) - - if dataLength == 0 { - return atree.SlabIndex{}, false, nil - } - - isStorageIndex := dataLength == storageIndexLength - if !isStorageIndex { - // Invalid data in register - - // TODO: add dedicated error type? - return atree.SlabIndex{}, false, errors.NewUnexpectedError( - "invalid storage index for storage map of account '%x': expected length %d, got %d", - address[:], storageIndexLength, dataLength, - ) - } - - return atree.SlabIndex(data), true, nil -} - func (s *Storage) recordContractUpdate( location common.AddressLocation, contractValue *interpreter.CompositeValue, @@ -606,23 +567,3 @@ func (UnreferencedRootSlabsError) IsInternalError() {} func (e UnreferencedRootSlabsError) Error() string { return fmt.Sprintf("slabs not referenced: %s", e.UnreferencedRootSlabIDs) } - -func writeSlabIndex( - ledger atree.Ledger, - address common.Address, - key []byte, - slabIndex atree.SlabIndex, -) error { - var err error - errors.WrapPanic(func() { - err = ledger.SetValue( - address[:], - key, - slabIndex[:], - ) - }) - if err != nil { - return interpreter.WrappedExternalError(err) - } - return nil -}