github.com/koko1123/flow-go-1@v0.29.6/fvm/state/state.go (about) 1 package state 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "fmt" 8 "strings" 9 10 "github.com/onflow/cadence/runtime/common" 11 "golang.org/x/exp/slices" 12 13 "github.com/koko1123/flow-go-1/fvm/errors" 14 "github.com/koko1123/flow-go-1/fvm/meter" 15 "github.com/koko1123/flow-go-1/model/flow" 16 ) 17 18 const ( 19 DefaultMaxKeySize = 16_000 // ~16KB 20 DefaultMaxValueSize = 256_000_000 // ~256MB 21 22 // Service level keys (owner is empty): 23 UUIDKey = "uuid" 24 AddressStateKey = "account_address_state" 25 26 // Account level keys 27 AccountKeyPrefix = "a." 28 AccountStatusKey = AccountKeyPrefix + "s" 29 CodeKeyPrefix = "code." 30 ContractNamesKey = "contract_names" 31 PublicKeyKeyPrefix = "public_key_" 32 ) 33 34 // State represents the execution state 35 // it holds draft of updates and captures 36 // all register touches 37 type State struct { 38 // NOTE: A committed state is no longer accessible. It can however be 39 // re-attached to another transaction and be committed (for cached result 40 // bookkeeping purpose). 41 committed bool 42 43 view View 44 meter *meter.Meter 45 updatedAddresses map[flow.Address]struct{} 46 stateLimits 47 } 48 49 type stateLimits struct { 50 maxKeySizeAllowed uint64 51 maxValueSizeAllowed uint64 52 } 53 54 type StateParameters struct { 55 meter.MeterParameters 56 57 stateLimits 58 } 59 60 func DefaultParameters() StateParameters { 61 return StateParameters{ 62 MeterParameters: meter.DefaultParameters(), 63 stateLimits: stateLimits{ 64 maxKeySizeAllowed: DefaultMaxKeySize, 65 maxValueSizeAllowed: DefaultMaxValueSize, 66 }, 67 } 68 } 69 70 // WithMeterParameters sets the state's meter parameters 71 func (params StateParameters) WithMeterParameters( 72 meterParams meter.MeterParameters, 73 ) StateParameters { 74 newParams := params 75 newParams.MeterParameters = meterParams 76 return newParams 77 } 78 79 // WithMaxKeySizeAllowed sets limit on max key size 80 func (params StateParameters) WithMaxKeySizeAllowed(limit uint64) StateParameters { 81 newParams := params 82 newParams.maxKeySizeAllowed = limit 83 return newParams 84 } 85 86 // WithMaxValueSizeAllowed sets limit on max value size 87 func (params StateParameters) WithMaxValueSizeAllowed(limit uint64) StateParameters { 88 newParams := params 89 newParams.maxValueSizeAllowed = limit 90 return newParams 91 } 92 93 // TODO(patrick): rm once https://github.com/onflow/flow-emulator/pull/245 94 // is integrated. 95 // 96 // WithMaxInteractionSizeAllowed sets limit on total byte interaction with ledger 97 func (params StateParameters) WithMaxInteractionSizeAllowed(limit uint64) StateParameters { 98 newParams := params 99 newParams.MeterParameters = newParams.MeterParameters.WithStorageInteractionLimit(limit) 100 return newParams 101 } 102 103 func (s *State) View() View { 104 return s.view 105 } 106 107 func (s *State) Meter() *meter.Meter { 108 return s.meter 109 } 110 111 type StateOption func(st *State) *State 112 113 // NewState constructs a new state 114 func NewState(view View, params StateParameters) *State { 115 m := meter.NewMeter(params.MeterParameters) 116 return &State{ 117 committed: false, 118 view: view, 119 meter: m, 120 updatedAddresses: make(map[flow.Address]struct{}), 121 stateLimits: params.stateLimits, 122 } 123 } 124 125 // NewChildWithMeterParams generates a new child state using the provide meter 126 // parameters. 127 func (s *State) NewChildWithMeterParams( 128 params meter.MeterParameters, 129 ) *State { 130 return &State{ 131 committed: false, 132 view: s.view.NewChild(), 133 meter: meter.NewMeter(params), 134 updatedAddresses: make(map[flow.Address]struct{}), 135 stateLimits: s.stateLimits, 136 } 137 } 138 139 // NewChild generates a new child state using the parent's meter parameters. 140 func (s *State) NewChild() *State { 141 return s.NewChildWithMeterParams(s.meter.MeterParameters) 142 } 143 144 // InteractionUsed returns the amount of ledger interaction (total ledger byte read + total ledger byte written) 145 func (s *State) InteractionUsed() uint64 { 146 return s.meter.TotalBytesOfStorageInteractions() 147 } 148 149 // RegisterUpdates returns the lists of register id / value that were updated. 150 func (s *State) RegisterUpdates() ([]flow.RegisterID, []flow.RegisterValue) { 151 return s.view.RegisterUpdates() 152 } 153 154 // Get returns a register value given owner and key 155 func (s *State) Get(owner, key string, enforceLimit bool) (flow.RegisterValue, error) { 156 if s.committed { 157 return nil, fmt.Errorf("cannot Get on a committed state") 158 } 159 160 var value []byte 161 var err error 162 163 if enforceLimit { 164 if err = s.checkSize(owner, key, []byte{}); err != nil { 165 return nil, err 166 } 167 } 168 169 if value, err = s.view.Get(owner, key); err != nil { 170 // wrap error into a fatal error 171 getError := errors.NewLedgerFailure(err) 172 // wrap with more info 173 return nil, fmt.Errorf("failed to read key %s on account %s: %w", PrintableKey(key), hex.EncodeToString([]byte(owner)), getError) 174 } 175 176 err = s.meter.MeterStorageRead( 177 meter.StorageInteractionKey{Owner: owner, Key: key}, 178 value, 179 enforceLimit) 180 181 return value, err 182 } 183 184 // Set updates state delta with a register update 185 func (s *State) Set(owner, key string, value flow.RegisterValue, enforceLimit bool) error { 186 if s.committed { 187 return fmt.Errorf("cannot Set on a committed state") 188 } 189 190 if enforceLimit { 191 if err := s.checkSize(owner, key, value); err != nil { 192 return err 193 } 194 } 195 196 if err := s.view.Set(owner, key, value); err != nil { 197 // wrap error into a fatal error 198 setError := errors.NewLedgerFailure(err) 199 // wrap with more info 200 return fmt.Errorf("failed to update key %s on account %s: %w", PrintableKey(key), hex.EncodeToString([]byte(owner)), setError) 201 } 202 203 err := s.meter.MeterStorageWrite( 204 meter.StorageInteractionKey{Owner: owner, Key: key}, 205 value, 206 enforceLimit, 207 ) 208 if err != nil { 209 return err 210 } 211 212 if address, isAddress := addressFromOwner(owner); isAddress { 213 s.updatedAddresses[address] = struct{}{} 214 } 215 216 return nil 217 } 218 219 // MeterComputation meters computation usage 220 func (s *State) MeterComputation(kind common.ComputationKind, intensity uint) error { 221 if s.committed { 222 return fmt.Errorf("cannot MeterComputation on a committed state") 223 } 224 225 return s.meter.MeterComputation(kind, intensity) 226 } 227 228 // TotalComputationUsed returns total computation used 229 func (s *State) TotalComputationUsed() uint64 { 230 return s.meter.TotalComputationUsed() 231 } 232 233 // ComputationIntensities returns computation intensities 234 func (s *State) ComputationIntensities() meter.MeteredComputationIntensities { 235 return s.meter.ComputationIntensities() 236 } 237 238 // TotalComputationLimit returns total computation limit 239 func (s *State) TotalComputationLimit() uint { 240 return s.meter.TotalComputationLimit() 241 } 242 243 // MeterMemory meters memory usage 244 func (s *State) MeterMemory(kind common.MemoryKind, intensity uint) error { 245 if s.committed { 246 return fmt.Errorf("cannot MeterMemory on a committed state") 247 } 248 249 return s.meter.MeterMemory(kind, intensity) 250 } 251 252 // MemoryIntensities returns computation intensities 253 func (s *State) MemoryIntensities() meter.MeteredMemoryIntensities { 254 return s.meter.MemoryIntensities() 255 } 256 257 // TotalMemoryEstimate returns total memory used 258 func (s *State) TotalMemoryEstimate() uint64 { 259 return s.meter.TotalMemoryEstimate() 260 } 261 262 // TotalMemoryLimit returns total memory limit 263 func (s *State) TotalMemoryLimit() uint { 264 return uint(s.meter.TotalMemoryLimit()) 265 } 266 267 func (s *State) MeterEmittedEvent(byteSize uint64) error { 268 if s.committed { 269 return fmt.Errorf("cannot MeterEmittedEvent on a committed state") 270 } 271 272 return s.meter.MeterEmittedEvent(byteSize) 273 } 274 275 func (s *State) TotalEmittedEventBytes() uint64 { 276 return s.meter.TotalEmittedEventBytes() 277 } 278 279 // MergeState applies the changes from a the given view to this view. 280 func (s *State) MergeState(other *State) error { 281 if s.committed { 282 return fmt.Errorf("cannot MergeState on a committed state") 283 } 284 285 err := s.view.MergeView(other.view) 286 if err != nil { 287 return errors.NewStateMergeFailure(err) 288 } 289 290 s.meter.MergeMeter(other.meter) 291 292 // apply address updates 293 for k, v := range other.updatedAddresses { 294 s.updatedAddresses[k] = v 295 } 296 297 return nil 298 } 299 300 // UpdatedAddresses returns a sorted list of addresses that were updated (at least 1 register update) 301 func (s *State) UpdatedAddresses() []flow.Address { 302 addresses := make([]flow.Address, 0, len(s.updatedAddresses)) 303 304 for k := range s.updatedAddresses { 305 addresses = append(addresses, k) 306 } 307 308 slices.SortFunc(addresses, func(a, b flow.Address) bool { 309 // reverse order to maintain compatibility with previous implementation. 310 return bytes.Compare(a[:], b[:]) >= 0 311 }) 312 313 return addresses 314 } 315 316 func (s *State) checkSize(owner, key string, value flow.RegisterValue) error { 317 keySize := uint64(len(owner) + len(key)) 318 valueSize := uint64(len(value)) 319 if keySize > s.maxKeySizeAllowed { 320 return errors.NewStateKeySizeLimitError(owner, key, keySize, s.maxKeySizeAllowed) 321 } 322 if valueSize > s.maxValueSizeAllowed { 323 return errors.NewStateValueSizeLimitError(value, valueSize, s.maxValueSizeAllowed) 324 } 325 return nil 326 } 327 328 func addressFromOwner(owner string) (flow.Address, bool) { 329 ownerBytes := []byte(owner) 330 if len(ownerBytes) != flow.AddressLength { 331 // not an address 332 return flow.EmptyAddress, false 333 } 334 address := flow.BytesToAddress(ownerBytes) 335 return address, true 336 } 337 338 // IsFVMStateKey returns true if the key is controlled by the fvm env and 339 // return false otherwise (key controlled by the cadence env) 340 func IsFVMStateKey(owner string, key string) bool { 341 // check if is a service level key (owner is empty) 342 // cases: 343 // - "", "uuid" 344 // - "", "account_address_state" 345 if len(owner) == 0 && (key == UUIDKey || key == AddressStateKey) { 346 return true 347 } 348 349 // check account level keys 350 // cases: 351 // - address, "contract_names" 352 // - address, "code.%s" (contract name) 353 // - address, "public_key_%d" (index) 354 // - address, "a.s" (account status) 355 return strings.HasPrefix(key, PublicKeyKeyPrefix) || 356 key == ContractNamesKey || 357 strings.HasPrefix(key, CodeKeyPrefix) || 358 key == AccountStatusKey 359 } 360 361 // This returns true if the key is a slab index for an account's ordered fields 362 // map. 363 // 364 // In general, each account's regular fields are stored in ordered map known 365 // only to cadence. Cadence encodes this map into bytes and split the bytes 366 // into slab chunks before storing the slabs into the ledger. 367 func IsSlabIndex(key string) bool { 368 return len(key) == 9 && key[0] == '$' 369 } 370 371 // PrintableKey formats slabs properly and avoids invalid utf8s 372 func PrintableKey(key string) string { 373 // slab 374 if IsSlabIndex(key) { 375 i := uint64(binary.BigEndian.Uint64([]byte(key[1:]))) 376 return fmt.Sprintf("$%d", i) 377 } 378 return fmt.Sprintf("#%x", []byte(key)) 379 }