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  }