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 }