github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/accounts.go (about) 1 package environment 2 3 import ( 4 "bytes" 5 "fmt" 6 "math" 7 "sort" 8 9 "github.com/fxamacker/cbor/v2" 10 "github.com/onflow/atree" 11 12 "github.com/onflow/flow-go/crypto" 13 "github.com/onflow/flow-go/crypto/hash" 14 "github.com/koko1123/flow-go-1/fvm/errors" 15 "github.com/koko1123/flow-go-1/fvm/state" 16 "github.com/koko1123/flow-go-1/model/flow" 17 ) 18 19 const ( 20 MaxPublicKeyCount = math.MaxUint64 21 ) 22 23 type Accounts interface { 24 Exists(address flow.Address) (bool, error) 25 Get(address flow.Address) (*flow.Account, error) 26 GetPublicKeyCount(address flow.Address) (uint64, error) 27 AppendPublicKey(address flow.Address, key flow.AccountPublicKey) error 28 GetPublicKey(address flow.Address, keyIndex uint64) (flow.AccountPublicKey, error) 29 SetPublicKey(address flow.Address, keyIndex uint64, publicKey flow.AccountPublicKey) ([]byte, error) 30 GetContractNames(address flow.Address) ([]string, error) 31 GetContract(contractName string, address flow.Address) ([]byte, error) 32 ContractExists(contractName string, address flow.Address) (bool, error) 33 SetContract(contractName string, address flow.Address, contract []byte) error 34 DeleteContract(contractName string, address flow.Address) error 35 Create(publicKeys []flow.AccountPublicKey, newAddress flow.Address) error 36 GetValue(address flow.Address, key string) (flow.RegisterValue, error) 37 CheckAccountNotFrozen(address flow.Address) error 38 GetStorageUsed(address flow.Address) (uint64, error) 39 SetValue(address flow.Address, key string, value flow.RegisterValue) error 40 AllocateStorageIndex(address flow.Address) (atree.StorageIndex, error) 41 SetAccountFrozen(address flow.Address, frozen bool) error 42 } 43 44 var _ Accounts = &StatefulAccounts{} 45 46 type StatefulAccounts struct { 47 txnState *state.TransactionState 48 } 49 50 func NewAccounts(txnState *state.TransactionState) *StatefulAccounts { 51 return &StatefulAccounts{ 52 txnState: txnState, 53 } 54 } 55 56 func (a *StatefulAccounts) AllocateStorageIndex(address flow.Address) (atree.StorageIndex, error) { 57 // get status 58 status, err := a.getAccountStatus(address) 59 if err != nil { 60 return atree.StorageIndex{}, err 61 } 62 63 // get and increment the index 64 index := status.StorageIndex() 65 newIndexBytes := index.Next() 66 67 // store nil so that the setValue for new allocated slabs would be faster 68 // and won't do ledger getValue for every new slabs (currently happening to compute storage size changes) 69 // this way the getValue would load this value from deltas 70 key := atree.SlabIndexToLedgerKey(index) 71 err = a.txnState.Set( 72 string(address.Bytes()), 73 string(key), 74 []byte{}, 75 false) 76 if err != nil { 77 return atree.StorageIndex{}, fmt.Errorf("failed to allocate an storage index: %w", err) 78 } 79 80 // update the storageIndex bytes 81 status.SetStorageIndex(newIndexBytes) 82 err = a.setAccountStatus(address, status) 83 if err != nil { 84 return atree.StorageIndex{}, fmt.Errorf("failed to allocate an storage index: %w", err) 85 } 86 return index, nil 87 } 88 89 func (a *StatefulAccounts) Get(address flow.Address) (*flow.Account, error) { 90 var ok bool 91 var err error 92 93 ok, err = a.Exists(address) 94 if err != nil { 95 return nil, err 96 } 97 98 if !ok { 99 return nil, errors.NewAccountNotFoundError(address) 100 } 101 contracts := make(map[string][]byte) 102 contractNames, err := a.getContractNames(address) 103 104 if err != nil { 105 return nil, err 106 } 107 108 for _, name := range contractNames { 109 contract, err := a.getContract(name, address) 110 if err != nil { 111 return nil, err 112 } 113 contracts[name] = contract 114 } 115 116 var publicKeys []flow.AccountPublicKey 117 publicKeys, err = a.GetPublicKeys(address) 118 if err != nil { 119 return nil, err 120 } 121 122 return &flow.Account{ 123 Address: address, 124 Keys: publicKeys, 125 Contracts: contracts, 126 }, nil 127 } 128 129 func (a *StatefulAccounts) Exists(address flow.Address) (bool, error) { 130 accStatusBytes, err := a.GetValue(address, state.AccountStatusKey) 131 if err != nil { 132 return false, err 133 } 134 135 // account doesn't exist if account status doesn't exist 136 if len(accStatusBytes) == 0 { 137 return false, nil 138 } 139 140 // check if we can construct account status from the value of this register 141 _, err = AccountStatusFromBytes(accStatusBytes) 142 if err != nil { 143 return false, err 144 } 145 146 return true, nil 147 } 148 149 // Create account sets all required registers on an address. 150 func (a *StatefulAccounts) Create(publicKeys []flow.AccountPublicKey, newAddress flow.Address) error { 151 exists, err := a.Exists(newAddress) 152 if err != nil { 153 return fmt.Errorf("failed to create a new account: %w", err) 154 } 155 if exists { 156 return errors.NewAccountAlreadyExistsError(newAddress) 157 } 158 159 accountStatus := NewAccountStatus() 160 accountStatus.SetStorageUsed(uint64(RegisterSize(newAddress, state.AccountStatusKey, accountStatus.ToBytes()))) 161 162 err = a.setAccountStatus(newAddress, accountStatus) 163 if err != nil { 164 return fmt.Errorf("failed to create a new account: %w", err) 165 } 166 return a.SetAllPublicKeys(newAddress, publicKeys) 167 } 168 169 func (a *StatefulAccounts) GetPublicKey(address flow.Address, keyIndex uint64) (flow.AccountPublicKey, error) { 170 publicKey, err := a.GetValue(address, KeyPublicKey(keyIndex)) 171 if err != nil { 172 return flow.AccountPublicKey{}, err 173 } 174 175 if len(publicKey) == 0 { 176 return flow.AccountPublicKey{}, errors.NewAccountPublicKeyNotFoundError(address, keyIndex) 177 } 178 179 decodedPublicKey, err := flow.DecodeAccountPublicKey(publicKey, keyIndex) 180 if err != nil { 181 return flow.AccountPublicKey{}, fmt.Errorf("failed to decode public key: %w", err) 182 } 183 184 return decodedPublicKey, nil 185 } 186 187 func (a *StatefulAccounts) GetPublicKeyCount(address flow.Address) (uint64, error) { 188 status, err := a.getAccountStatus(address) 189 if err != nil { 190 return 0, fmt.Errorf("failed to get public key count: %w", err) 191 } 192 return status.PublicKeyCount(), nil 193 } 194 195 func (a *StatefulAccounts) setPublicKeyCount(address flow.Address, count uint64) error { 196 status, err := a.getAccountStatus(address) 197 if err != nil { 198 return fmt.Errorf("failed to set public key count for account (%s): %w", address.String(), err) 199 } 200 201 status.SetPublicKeyCount(count) 202 203 err = a.setAccountStatus(address, status) 204 if err != nil { 205 return fmt.Errorf("failed to set public key count for account (%s): %w", address.String(), err) 206 } 207 return nil 208 } 209 210 func (a *StatefulAccounts) GetPublicKeys(address flow.Address) (publicKeys []flow.AccountPublicKey, err error) { 211 count, err := a.GetPublicKeyCount(address) 212 if err != nil { 213 return nil, fmt.Errorf("failed to get public key count of account: %w", err) 214 } 215 publicKeys = make([]flow.AccountPublicKey, count) 216 217 for i := uint64(0); i < count; i++ { 218 publicKey, err := a.GetPublicKey(address, i) 219 if err != nil { 220 return nil, err 221 } 222 223 publicKeys[i] = publicKey 224 } 225 226 return publicKeys, nil 227 } 228 229 func (a *StatefulAccounts) SetPublicKey( 230 address flow.Address, 231 keyIndex uint64, 232 publicKey flow.AccountPublicKey, 233 ) (encodedPublicKey []byte, err error) { 234 err = publicKey.Validate() 235 if err != nil { 236 encoded, _ := publicKey.MarshalJSON() 237 return nil, errors.NewValueErrorf(string(encoded), "invalid public key value: %w", err) 238 } 239 240 encodedPublicKey, err = flow.EncodeAccountPublicKey(publicKey) 241 if err != nil { 242 encoded, _ := publicKey.MarshalJSON() 243 return nil, errors.NewValueErrorf(string(encoded), "invalid public key value: %w", err) 244 } 245 246 err = a.SetValue(address, KeyPublicKey(keyIndex), encodedPublicKey) 247 248 return encodedPublicKey, err 249 } 250 251 func (a *StatefulAccounts) SetAllPublicKeys(address flow.Address, publicKeys []flow.AccountPublicKey) error { 252 253 count := uint64(len(publicKeys)) // len returns int and this will not exceed uint64 254 255 if count >= MaxPublicKeyCount { 256 return errors.NewAccountPublicKeyLimitError(address, count, MaxPublicKeyCount) 257 } 258 259 for i, publicKey := range publicKeys { 260 _, err := a.SetPublicKey(address, uint64(i), publicKey) 261 if err != nil { 262 return err 263 } 264 } 265 266 return a.setPublicKeyCount(address, count) 267 } 268 269 func (a *StatefulAccounts) AppendPublicKey(address flow.Address, publicKey flow.AccountPublicKey) error { 270 271 if !IsValidAccountKeyHashAlgo(publicKey.HashAlgo) { 272 return errors.NewValueErrorf(publicKey.HashAlgo.String(), "hashing algorithm type not found") 273 } 274 275 if !IsValidAccountKeySignAlgo(publicKey.SignAlgo) { 276 return errors.NewValueErrorf(publicKey.SignAlgo.String(), "signature algorithm type not found") 277 } 278 279 count, err := a.GetPublicKeyCount(address) 280 if err != nil { 281 return err 282 } 283 284 if count >= MaxPublicKeyCount { 285 return errors.NewAccountPublicKeyLimitError(address, count+1, MaxPublicKeyCount) 286 } 287 288 _, err = a.SetPublicKey(address, count, publicKey) 289 if err != nil { 290 return err 291 } 292 293 return a.setPublicKeyCount(address, count+1) 294 } 295 296 func IsValidAccountKeySignAlgo(algo crypto.SigningAlgorithm) bool { 297 switch algo { 298 case crypto.ECDSAP256, crypto.ECDSASecp256k1: 299 return true 300 default: 301 return false 302 } 303 } 304 305 func IsValidAccountKeyHashAlgo(algo hash.HashingAlgorithm) bool { 306 switch algo { 307 case hash.SHA2_256, hash.SHA3_256: 308 return true 309 default: 310 return false 311 } 312 } 313 314 func ContractKey(contractName string) string { 315 return state.CodeKeyPrefix + contractName 316 } 317 318 func (a *StatefulAccounts) getContract(contractName string, address flow.Address) ([]byte, error) { 319 320 contract, err := a.GetValue(address, ContractKey(contractName)) 321 if err != nil { 322 return nil, err 323 } 324 325 return contract, nil 326 } 327 328 func (a *StatefulAccounts) setContract(contractName string, address flow.Address, contract []byte) error { 329 ok, err := a.Exists(address) 330 if err != nil { 331 return err 332 } 333 334 if !ok { 335 return errors.NewAccountNotFoundError(address) 336 } 337 338 var prevContract []byte 339 prevContract, err = a.GetValue(address, ContractKey(contractName)) 340 if err != nil { 341 return errors.NewContractNotFoundError(address, contractName) 342 } 343 344 // skip updating if the new contract equals the old 345 if bytes.Equal(prevContract, contract) { 346 return nil 347 } 348 349 err = a.SetValue(address, ContractKey(contractName), contract) 350 if err != nil { 351 return err 352 } 353 354 return nil 355 } 356 357 func (a *StatefulAccounts) setContractNames(contractNames contractNames, address flow.Address) error { 358 ok, err := a.Exists(address) 359 if err != nil { 360 return err 361 } 362 363 if !ok { 364 return errors.NewAccountNotFoundError(address) 365 } 366 var buf bytes.Buffer 367 cborEncoder := cbor.NewEncoder(&buf) 368 err = cborEncoder.Encode(contractNames) 369 if err != nil { 370 return errors.NewEncodingFailuref( 371 err, 372 "cannot encode contract names: %s", 373 contractNames) 374 } 375 newContractNames := buf.Bytes() 376 377 var prevContractNames []byte 378 prevContractNames, err = a.GetValue(address, state.ContractNamesKey) 379 if err != nil { 380 return fmt.Errorf("cannot retrieve current contract names: %w", err) 381 } 382 383 // skip updating if the new contract names equal the old 384 if bytes.Equal(prevContractNames, newContractNames) { 385 return nil 386 } 387 388 return a.SetValue(address, state.ContractNamesKey, newContractNames) 389 } 390 391 // GetStorageUsed returns the amount of storage used in bytes by this account 392 func (a *StatefulAccounts) GetStorageUsed(address flow.Address) (uint64, error) { 393 status, err := a.getAccountStatus(address) 394 if err != nil { 395 return 0, fmt.Errorf("failed to get storage used: %w", err) 396 } 397 return status.StorageUsed(), nil 398 } 399 400 func (a *StatefulAccounts) setStorageUsed(address flow.Address, used uint64) error { 401 status, err := a.getAccountStatus(address) 402 if err != nil { 403 return fmt.Errorf("failed to set storage used: %w", err) 404 } 405 406 status.SetStorageUsed(used) 407 408 err = a.setAccountStatus(address, status) 409 if err != nil { 410 return fmt.Errorf("failed to set storage used: %w", err) 411 } 412 return nil 413 } 414 415 func (a *StatefulAccounts) GetValue(address flow.Address, key string) (flow.RegisterValue, error) { 416 return a.txnState.Get( 417 string(address.Bytes()), 418 key, 419 a.txnState.EnforceLimits()) 420 } 421 422 // SetValue sets a value in address' storage 423 func (a *StatefulAccounts) SetValue(address flow.Address, key string, value flow.RegisterValue) error { 424 err := a.updateRegisterSizeChange(address, key, value) 425 if err != nil { 426 return fmt.Errorf("failed to update storage used by key %s on account %s: %w", state.PrintableKey(key), address, err) 427 } 428 return a.txnState.Set( 429 string(address.Bytes()), 430 key, 431 value, 432 a.txnState.EnforceLimits()) 433 434 } 435 436 func (a *StatefulAccounts) updateRegisterSizeChange(address flow.Address, key string, value flow.RegisterValue) error { 437 if key == state.AccountStatusKey { 438 // size of this register is always fixed size 439 // don't double check this to save time and prevent recursion 440 return nil 441 } 442 oldValue, err := a.GetValue(address, key) 443 if err != nil { 444 return err 445 } 446 447 sizeChange := int64(RegisterSize(address, key, value) - RegisterSize(address, key, oldValue)) 448 if sizeChange == 0 { 449 // register size has not changed. Nothing to do 450 return nil 451 } 452 453 oldSize, err := a.GetStorageUsed(address) 454 if err != nil { 455 return err 456 } 457 458 // two paths to avoid casting uint to int 459 var newSize uint64 460 if sizeChange < 0 { 461 absChange := uint64(-sizeChange) 462 if absChange > oldSize { 463 // should never happen 464 return fmt.Errorf("storage used by key %s on account %s would be negative", state.PrintableKey(key), address.Hex()) 465 } 466 newSize = oldSize - absChange 467 } else { 468 absChange := uint64(sizeChange) 469 newSize = oldSize + absChange 470 } 471 472 // this puts us back in the setValue method. 473 // The difference is that storage_used update exits early from this function so there isn't any recursion. 474 return a.setStorageUsed(address, newSize) 475 } 476 477 func RegisterSize(address flow.Address, key string, value flow.RegisterValue) int { 478 if len(value) == 0 { 479 // registers with empty value won't (or don't) exist when stored 480 return 0 481 } 482 size := 0 483 // additional 2 is for len prefixes when encoding is happening 484 // we might get rid of these 2s in the future 485 size += 2 + len(string(address.Bytes())) 486 size += 2 + len(key) 487 size += len(value) 488 return size 489 } 490 491 // TODO replace with touch 492 // TODO handle errors 493 func (a *StatefulAccounts) touch(address flow.Address, key string) { 494 _, _ = a.txnState.Get( 495 string(address.Bytes()), 496 key, 497 a.txnState.EnforceLimits()) 498 } 499 500 func (a *StatefulAccounts) TouchContract(contractName string, address flow.Address) { 501 contractNames, err := a.getContractNames(address) 502 if err != nil { 503 panic(err) 504 } 505 if contractNames.Has(contractName) { 506 a.touch(address, ContractKey(contractName)) 507 } 508 } 509 510 // GetContractNames gets a sorted list of names of contracts deployed on an address 511 func (a *StatefulAccounts) GetContractNames(address flow.Address) ([]string, error) { 512 return a.getContractNames(address) 513 } 514 515 func (a *StatefulAccounts) getContractNames(address flow.Address) (contractNames, error) { 516 // TODO return fatal error if can't fetch 517 encContractNames, err := a.GetValue(address, state.ContractNamesKey) 518 if err != nil { 519 return nil, fmt.Errorf("cannot get deployed contract names: %w", err) 520 } 521 identifiers := make([]string, 0) 522 if len(encContractNames) > 0 { 523 buf := bytes.NewReader(encContractNames) 524 cborDecoder := cbor.NewDecoder(buf) 525 err = cborDecoder.Decode(&identifiers) 526 if err != nil { 527 return nil, fmt.Errorf("cannot decode deployed contract names %x: %w", encContractNames, err) 528 } 529 } 530 return identifiers, nil 531 } 532 533 func (a *StatefulAccounts) ContractExists(contractName string, address flow.Address) (bool, error) { 534 contractNames, err := a.getContractNames(address) 535 if err != nil { 536 return false, err 537 } 538 return contractNames.Has(contractName), nil 539 } 540 541 func (a *StatefulAccounts) GetContract(contractName string, address flow.Address) ([]byte, error) { 542 // we optimized the happy case here, we look up for the content of the contract 543 // and if its not there we check if contract exists or if this is another problem. 544 code, err := a.getContract(contractName, address) 545 if err != nil || len(code) == 0 { 546 exists, err := a.ContractExists(contractName, address) 547 if err != nil { 548 return nil, err 549 } 550 if !exists { 551 return nil, nil 552 } 553 } 554 return code, err 555 } 556 557 func (a *StatefulAccounts) SetContract(contractName string, address flow.Address, contract []byte) error { 558 contractNames, err := a.getContractNames(address) 559 if err != nil { 560 return err 561 } 562 err = a.setContract(contractName, address, contract) 563 if err != nil { 564 return err 565 } 566 contractNames.add(contractName) 567 return a.setContractNames(contractNames, address) 568 } 569 570 func (a *StatefulAccounts) DeleteContract(contractName string, address flow.Address) error { 571 contractNames, err := a.getContractNames(address) 572 if err != nil { 573 return err 574 } 575 if !contractNames.Has(contractName) { 576 return nil 577 } 578 err = a.setContract(contractName, address, nil) 579 if err != nil { 580 return err 581 } 582 contractNames.remove(contractName) 583 return a.setContractNames(contractNames, address) 584 } 585 586 func (a *StatefulAccounts) getAccountStatus(address flow.Address) (*AccountStatus, error) { 587 statusBytes, err := a.GetValue(address, state.AccountStatusKey) 588 if err != nil { 589 return nil, fmt.Errorf("failed to load account status for the account (%s): %w", address.String(), err) 590 } 591 if len(statusBytes) == 0 { 592 return nil, errors.NewAccountNotFoundError(address) 593 } 594 return AccountStatusFromBytes(statusBytes) 595 } 596 597 func (a *StatefulAccounts) setAccountStatus(address flow.Address, status *AccountStatus) error { 598 err := a.SetValue(address, state.AccountStatusKey, status.ToBytes()) 599 if err != nil { 600 return fmt.Errorf("failed to store the account status for account (%s): %w", address.String(), err) 601 } 602 return nil 603 } 604 605 func (a *StatefulAccounts) GetAccountFrozen(address flow.Address) (bool, error) { 606 status, err := a.getAccountStatus(address) 607 if err != nil { 608 return false, err 609 } 610 return status.IsAccountFrozen(), nil 611 } 612 613 func (a *StatefulAccounts) SetAccountFrozen(address flow.Address, frozen bool) error { 614 status, err := a.getAccountStatus(address) 615 if err != nil { 616 return err 617 } 618 status.SetFrozenFlag(frozen) 619 return a.setAccountStatus(address, status) 620 } 621 622 // handy function to error out if account is frozen 623 func (a *StatefulAccounts) CheckAccountNotFrozen(address flow.Address) error { 624 frozen, err := a.GetAccountFrozen(address) 625 if err != nil { 626 return fmt.Errorf("cannot check account freeze status: %w", err) 627 } 628 if frozen { 629 return errors.NewFrozenAccountError(address) 630 } 631 return nil 632 } 633 634 // contractNames container for a list of contract names. Should always be sorted. 635 // To ensure this, don't sort while reading it from storage, but sort it while adding/removing elements 636 type contractNames []string 637 638 func (l contractNames) Has(contractNames string) bool { 639 i := sort.SearchStrings(l, contractNames) 640 return i != len(l) && l[i] == contractNames 641 } 642 func (l *contractNames) add(contractNames string) { 643 i := sort.SearchStrings(*l, contractNames) 644 if i != len(*l) && (*l)[i] == contractNames { 645 // list already contains element 646 return 647 } 648 *l = append(*l, "") 649 copy((*l)[i+1:], (*l)[i:]) 650 (*l)[i] = contractNames 651 } 652 func (l *contractNames) remove(contractName string) { 653 i := sort.SearchStrings(*l, contractName) 654 if i == len(*l) || (*l)[i] != contractName { 655 // list does not contain the element 656 return 657 } 658 *l = append((*l)[:i], (*l)[i+1:]...) 659 } 660 661 func KeyPublicKey(index uint64) string { 662 return fmt.Sprintf("public_key_%d", index) 663 }