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