github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/value_store.go (about)

     1  package environment
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/atree"
     7  
     8  	"github.com/koko1123/flow-go-1/fvm/errors"
     9  	"github.com/koko1123/flow-go-1/fvm/state"
    10  	"github.com/koko1123/flow-go-1/fvm/tracing"
    11  	"github.com/koko1123/flow-go-1/model/flow"
    12  	"github.com/koko1123/flow-go-1/module/trace"
    13  )
    14  
    15  // ValueStore provides read/write access to the account storage.
    16  type ValueStore interface {
    17  	GetValue(owner []byte, key []byte) ([]byte, error)
    18  
    19  	SetValue(owner, key, value []byte) error
    20  
    21  	ValueExists(owner []byte, key []byte) (bool, error)
    22  
    23  	AllocateStorageIndex(owner []byte) (atree.StorageIndex, error)
    24  }
    25  
    26  type ParseRestrictedValueStore struct {
    27  	txnState *state.TransactionState
    28  	impl     ValueStore
    29  }
    30  
    31  func NewParseRestrictedValueStore(
    32  	txnState *state.TransactionState,
    33  	impl ValueStore,
    34  ) ValueStore {
    35  	return ParseRestrictedValueStore{
    36  		txnState: txnState,
    37  		impl:     impl,
    38  	}
    39  }
    40  
    41  func (store ParseRestrictedValueStore) GetValue(
    42  	owner []byte,
    43  	key []byte,
    44  ) (
    45  	[]byte,
    46  	error,
    47  ) {
    48  	return parseRestrict2Arg1Ret(
    49  		store.txnState,
    50  		trace.FVMEnvGetValue,
    51  		store.impl.GetValue,
    52  		owner,
    53  		key)
    54  }
    55  
    56  func (store ParseRestrictedValueStore) SetValue(
    57  	owner []byte,
    58  	key []byte,
    59  	value []byte,
    60  ) error {
    61  	return parseRestrict3Arg(
    62  		store.txnState,
    63  		trace.FVMEnvSetValue,
    64  		store.impl.SetValue,
    65  		owner,
    66  		key,
    67  		value)
    68  }
    69  
    70  func (store ParseRestrictedValueStore) ValueExists(
    71  	owner []byte,
    72  	key []byte,
    73  ) (
    74  	bool,
    75  	error,
    76  ) {
    77  	return parseRestrict2Arg1Ret(
    78  		store.txnState,
    79  		trace.FVMEnvValueExists,
    80  		store.impl.ValueExists,
    81  		owner,
    82  		key)
    83  }
    84  
    85  func (store ParseRestrictedValueStore) AllocateStorageIndex(
    86  	owner []byte,
    87  ) (
    88  	atree.StorageIndex,
    89  	error,
    90  ) {
    91  	return parseRestrict1Arg1Ret(
    92  		store.txnState,
    93  		trace.FVMEnvAllocateStorageIndex,
    94  		store.impl.AllocateStorageIndex,
    95  		owner)
    96  }
    97  
    98  type valueStore struct {
    99  	tracer tracing.TracerSpan
   100  	meter  Meter
   101  
   102  	accounts Accounts
   103  }
   104  
   105  func NewValueStore(
   106  	tracer tracing.TracerSpan,
   107  	meter Meter,
   108  	accounts Accounts,
   109  ) ValueStore {
   110  	return &valueStore{
   111  		tracer:   tracer,
   112  		meter:    meter,
   113  		accounts: accounts,
   114  	}
   115  }
   116  
   117  func (store *valueStore) GetValue(
   118  	owner []byte,
   119  	keyBytes []byte,
   120  ) (
   121  	[]byte,
   122  	error,
   123  ) {
   124  	defer store.tracer.StartChildSpan(trace.FVMEnvGetValue).End()
   125  
   126  	key := string(keyBytes)
   127  
   128  	address := flow.BytesToAddress(owner)
   129  	if state.IsFVMStateKey(string(owner), key) {
   130  		return nil, errors.NewInvalidFVMStateAccessError(address, key, "read")
   131  	}
   132  
   133  	v, err := store.accounts.GetValue(address, key)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("get value failed: %w", err)
   136  	}
   137  
   138  	err = store.meter.MeterComputation(ComputationKindGetValue, uint(len(v)))
   139  	if err != nil {
   140  		return nil, fmt.Errorf("get value failed: %w", err)
   141  	}
   142  	return v, nil
   143  }
   144  
   145  // TODO disable SetValue for scripts, right now the view changes are discarded
   146  func (store *valueStore) SetValue(
   147  	owner []byte,
   148  	keyBytes []byte,
   149  	value []byte,
   150  ) error {
   151  	defer store.tracer.StartChildSpan(trace.FVMEnvSetValue).End()
   152  
   153  	key := string(keyBytes)
   154  
   155  	address := flow.BytesToAddress(owner)
   156  	if state.IsFVMStateKey(string(owner), key) {
   157  		return errors.NewInvalidFVMStateAccessError(address, key, "modify")
   158  	}
   159  
   160  	err := store.meter.MeterComputation(
   161  		ComputationKindSetValue,
   162  		uint(len(value)))
   163  	if err != nil {
   164  		return fmt.Errorf("set value failed: %w", err)
   165  	}
   166  
   167  	err = store.accounts.SetValue(address, key, value)
   168  	if err != nil {
   169  		return fmt.Errorf("set value failed: %w", err)
   170  	}
   171  	return nil
   172  }
   173  
   174  func (store *valueStore) ValueExists(
   175  	owner []byte,
   176  	key []byte,
   177  ) (
   178  	exists bool,
   179  	err error,
   180  ) {
   181  	defer store.tracer.StartChildSpan(trace.FVMEnvValueExists).End()
   182  
   183  	err = store.meter.MeterComputation(ComputationKindValueExists, 1)
   184  	if err != nil {
   185  		return false, fmt.Errorf("check value existence failed: %w", err)
   186  	}
   187  
   188  	v, err := store.GetValue(owner, key)
   189  	if err != nil {
   190  		return false, fmt.Errorf("check value existence failed: %w", err)
   191  	}
   192  
   193  	return len(v) > 0, nil
   194  }
   195  
   196  // AllocateStorageIndex allocates new storage index under the owner accounts
   197  // to store a new register.
   198  func (store *valueStore) AllocateStorageIndex(
   199  	owner []byte,
   200  ) (
   201  	atree.StorageIndex,
   202  	error,
   203  ) {
   204  	defer store.tracer.StartChildSpan(trace.FVMEnvAllocateStorageIndex).End()
   205  
   206  	err := store.meter.MeterComputation(ComputationKindAllocateStorageIndex, 1)
   207  	if err != nil {
   208  		return atree.StorageIndex{}, fmt.Errorf(
   209  			"allocate storage index failed: %w",
   210  			err)
   211  	}
   212  
   213  	v, err := store.accounts.AllocateStorageIndex(flow.BytesToAddress(owner))
   214  	if err != nil {
   215  		return atree.StorageIndex{}, fmt.Errorf(
   216  			"storage address allocation failed: %w",
   217  			err)
   218  	}
   219  	return v, nil
   220  }