Skip to content

Commit

Permalink
refactor slab index register reading/writing to separate file and imp…
Browse files Browse the repository at this point in the history
…rove naming
  • Loading branch information
turbolent committed Nov 18, 2024
1 parent 4addf32 commit 4fd610a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 67 deletions.
4 changes: 2 additions & 2 deletions runtime/account_storage_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand All @@ -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()),
Expand Down
10 changes: 5 additions & 5 deletions runtime/account_storage_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,23 +238,23 @@ func (s *AccountStorageV2) writeAccountStorageSlabIndex(
address common.Address,
slabIndex atree.SlabIndex,
) error {
return writeSlabIndex(
return writeSlabIndexToRegister(
s.ledger,
address,
[]byte(AccountStorageKey),
slabIndex,
)
}

func getAccountStorageSlabIndex(
func readAccountStorageSlabIndexFromRegister(
ledger atree.Ledger,
address common.Address,
) (
atree.SlabIndex,
bool,
error,
) {
return getSlabIndexFromRegisterValue(
return readSlabIndexFromRegister(
ledger,
address,
[]byte(AccountStorageKey),
Expand All @@ -269,7 +269,7 @@ func getAccountStorageMapFromRegister(
*interpreter.AccountStorageMap,
error,
) {
slabIndex, registerExists, err := getAccountStorageSlabIndex(
slabIndex, registerExists, err := readAccountStorageSlabIndexFromRegister(
ledger,
address,
)
Expand All @@ -293,7 +293,7 @@ func hasAccountStorageMap(
address common.Address,
) (bool, error) {

_, registerExists, err := getAccountStorageSlabIndex(
_, registerExists, err := readAccountStorageSlabIndexFromRegister(
ledger,
address,
)
Expand Down
86 changes: 86 additions & 0 deletions runtime/slabindex.go
Original file line number Diff line number Diff line change
@@ -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)
}

Check warning on line 46 in runtime/slabindex.go

View check run for this annotation

Codecov / codecov/patch

runtime/slabindex.go#L45-L46

Added lines #L45 - L46 were not covered by tests

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,
)
}

Check warning on line 63 in runtime/slabindex.go

View check run for this annotation

Codecov / codecov/patch

runtime/slabindex.go#L56-L63

Added lines #L56 - L63 were not covered by tests

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)
}

Check warning on line 84 in runtime/slabindex.go

View check run for this annotation

Codecov / codecov/patch

runtime/slabindex.go#L83-L84

Added lines #L83 - L84 were not covered by tests
return nil
}
61 changes: 1 addition & 60 deletions runtime/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}

0 comments on commit 4fd610a

Please sign in to comment.