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  }