Skip to content

[v1.4] Merge feature branch: Revert removal of support for storage format v1 #3979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions runtime/account_storage_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* 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 (
"sort"

"github.com/onflow/atree"

"github.com/onflow/cadence/common"
"github.com/onflow/cadence/errors"
"github.com/onflow/cadence/interpreter"
)

type AccountStorageV1 struct {
ledger atree.Ledger
slabStorage atree.SlabStorage
memoryGauge common.MemoryGauge

// newDomainStorageMapSlabIndices contains root slab indices of new domain storage maps.
// The indices are saved using Ledger.SetValue() during commit().
// Key is StorageDomainKey{common.StorageDomain, Address} and value is 8-byte slab index.
newDomainStorageMapSlabIndices map[interpreter.StorageDomainKey]atree.SlabIndex
}

func NewAccountStorageV1(
ledger atree.Ledger,
slabStorage atree.SlabStorage,
memoryGauge common.MemoryGauge,
) *AccountStorageV1 {
return &AccountStorageV1{
ledger: ledger,
slabStorage: slabStorage,
memoryGauge: memoryGauge,
}
}

func (s *AccountStorageV1) GetDomainStorageMap(
address common.Address,
domain common.StorageDomain,
createIfNotExists bool,
) (
domainStorageMap *interpreter.DomainStorageMap,
) {
var err error
domainStorageMap, err = getDomainStorageMapFromV1DomainRegister(
s.ledger,
s.slabStorage,
address,
domain,
)
if err != nil {
panic(err)
}

if domainStorageMap == nil && createIfNotExists {
domainStorageMap = s.storeNewDomainStorageMap(address, domain)
}

return domainStorageMap
}

func (s *AccountStorageV1) storeNewDomainStorageMap(
address common.Address,
domain common.StorageDomain,
) *interpreter.DomainStorageMap {

domainStorageMap := interpreter.NewDomainStorageMap(
s.memoryGauge,
s.slabStorage,
atree.Address(address),
)

slabIndex := domainStorageMap.SlabID().Index()

storageKey := interpreter.NewStorageDomainKey(s.memoryGauge, address, domain)

if s.newDomainStorageMapSlabIndices == nil {
s.newDomainStorageMapSlabIndices = map[interpreter.StorageDomainKey]atree.SlabIndex{}
}
s.newDomainStorageMapSlabIndices[storageKey] = slabIndex

return domainStorageMap
}

func (s *AccountStorageV1) commit() error {

switch len(s.newDomainStorageMapSlabIndices) {
case 0:
// Nothing to commit.
return nil

case 1:
// Optimize for the common case of a single domain storage map.

var updated int
for storageDomainKey, slabIndex := range s.newDomainStorageMapSlabIndices { //nolint:maprange
if updated > 0 {
panic(errors.NewUnreachableError())
}

err := s.writeStorageDomainSlabIndex(
storageDomainKey,
slabIndex,
)
if err != nil {
return err
}

updated++
}

default:
// Sort the indices to ensure deterministic order

type domainStorageMapSlabIndex struct {
StorageDomainKey interpreter.StorageDomainKey
SlabIndex atree.SlabIndex
}

slabIndices := make([]domainStorageMapSlabIndex, 0, len(s.newDomainStorageMapSlabIndices))
for storageDomainKey, slabIndex := range s.newDomainStorageMapSlabIndices { //nolint:maprange
slabIndices = append(
slabIndices,
domainStorageMapSlabIndex{
StorageDomainKey: storageDomainKey,
SlabIndex: slabIndex,
},
)
}
sort.Slice(
slabIndices,
func(i, j int) bool {
slabIndex1 := slabIndices[i]
slabIndex2 := slabIndices[j]
domainKey1 := slabIndex1.StorageDomainKey
domainKey2 := slabIndex2.StorageDomainKey
return domainKey1.Compare(domainKey2) < 0
},
)

for _, slabIndex := range slabIndices {
err := s.writeStorageDomainSlabIndex(
slabIndex.StorageDomainKey,
slabIndex.SlabIndex,
)
if err != nil {
return err
}
}
}

s.newDomainStorageMapSlabIndices = nil

return nil
}

func (s *AccountStorageV1) writeStorageDomainSlabIndex(
storageDomainKey interpreter.StorageDomainKey,
slabIndex atree.SlabIndex,
) error {
return writeSlabIndexToRegister(
s.ledger,
storageDomainKey.Address,
[]byte(storageDomainKey.Domain.Identifier()),
slabIndex,
)
}

// getDomainStorageMapFromV1DomainRegister returns domain storage map from legacy domain register.
func getDomainStorageMapFromV1DomainRegister(
ledger atree.Ledger,
storage atree.SlabStorage,
address common.Address,
domain common.StorageDomain,
) (*interpreter.DomainStorageMap, error) {

domainStorageSlabIndex, domainRegisterExists, err := readSlabIndexFromRegister(
ledger,
address,
[]byte(domain.Identifier()),
)
if err != nil {
return nil, err
}
if !domainRegisterExists {
return nil, nil
}

slabID := atree.NewSlabID(
atree.Address(address),
domainStorageSlabIndex,
)

return interpreter.NewDomainStorageMapWithRootID(storage, slabID), nil
}
39 changes: 27 additions & 12 deletions runtime/account_storage.go → runtime/account_storage_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/onflow/cadence/interpreter"
)

type AccountStorage struct {
type AccountStorageV2 struct {
ledger atree.Ledger
slabStorage atree.SlabStorage
memoryGauge common.MemoryGauge
Expand All @@ -41,19 +41,19 @@ type AccountStorage struct {
newAccountStorageMapSlabIndices map[common.Address]atree.SlabIndex
}

func NewAccountStorage(
func NewAccountStorageV2(
ledger atree.Ledger,
slabStorage atree.SlabStorage,
memoryGauge common.MemoryGauge,
) *AccountStorage {
return &AccountStorage{
) *AccountStorageV2 {
return &AccountStorageV2{
ledger: ledger,
slabStorage: slabStorage,
memoryGauge: memoryGauge,
}
}

func (s *AccountStorage) GetDomainStorageMap(
func (s *AccountStorageV2) GetDomainStorageMap(
storageMutationTracker interpreter.StorageMutationTracker,
address common.Address,
domain common.StorageDomain,
Expand All @@ -80,7 +80,7 @@ func (s *AccountStorage) GetDomainStorageMap(
}

// getAccountStorageMap returns AccountStorageMap if exists, or nil otherwise.
func (s *AccountStorage) getAccountStorageMap(
func (s *AccountStorageV2) getAccountStorageMap(
address common.Address,
) (
accountStorageMap *interpreter.AccountStorageMap,
Expand Down Expand Up @@ -118,7 +118,7 @@ func (s *AccountStorage) getAccountStorageMap(
return
}

func (s *AccountStorage) cacheAccountStorageMap(
func (s *AccountStorageV2) cacheAccountStorageMap(
address common.Address,
accountStorageMap *interpreter.AccountStorageMap,
) {
Expand All @@ -128,7 +128,7 @@ func (s *AccountStorage) cacheAccountStorageMap(
s.cachedAccountStorageMaps[address] = accountStorageMap
}

func (s *AccountStorage) storeNewAccountStorageMap(
func (s *AccountStorageV2) storeNewAccountStorageMap(
address common.Address,
) *interpreter.AccountStorageMap {

Expand All @@ -153,7 +153,7 @@ func (s *AccountStorage) storeNewAccountStorageMap(
return accountStorageMap
}

func (s *AccountStorage) SetNewAccountStorageMapSlabIndex(
func (s *AccountStorageV2) SetNewAccountStorageMapSlabIndex(
address common.Address,
slabIndex atree.SlabIndex,
) {
Expand All @@ -163,7 +163,7 @@ func (s *AccountStorage) SetNewAccountStorageMapSlabIndex(
s.newAccountStorageMapSlabIndices[address] = slabIndex
}

func (s *AccountStorage) commit() error {
func (s *AccountStorageV2) commit() error {
switch len(s.newAccountStorageMapSlabIndices) {
case 0:
// Nothing to commit.
Expand Down Expand Up @@ -234,7 +234,7 @@ func (s *AccountStorage) commit() error {
return nil
}

func (s *AccountStorage) writeAccountStorageSlabIndex(
func (s *AccountStorageV2) writeAccountStorageSlabIndex(
address common.Address,
slabIndex atree.SlabIndex,
) error {
Expand Down Expand Up @@ -288,7 +288,22 @@ func getAccountStorageMapFromRegister(
return interpreter.NewAccountStorageMapWithRootID(slabStorage, slabID), nil
}

func (s *AccountStorage) cachedRootSlabIDs() []atree.SlabID {
func hasAccountStorageMap(
ledger atree.Ledger,
address common.Address,
) (bool, error) {

_, registerExists, err := readAccountStorageSlabIndexFromRegister(
ledger,
address,
)
if err != nil {
return false, err
}
return registerExists, nil
}

func (s *AccountStorageV2) cachedRootSlabIDs() []atree.SlabID {

var slabIDs []atree.SlabID

Expand Down
4 changes: 3 additions & 1 deletion runtime/contract_function_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ func (executor *contractFunctionExecutor) preprocess() (err error) {

runtimeInterface := context.Interface

config := executor.runtime.Config()

storage := NewStorage(
runtimeInterface,
runtimeInterface,
Expand All @@ -113,7 +115,7 @@ func (executor *contractFunctionExecutor) preprocess() (err error) {

environment := context.Environment
if environment == nil {
environment = NewBaseInterpreterEnvironment(executor.runtime.Config())
environment = NewBaseInterpreterEnvironment(config)
}
environment.Configure(
runtimeInterface,
Expand Down
Loading
Loading