github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/accounts_test.go (about)

     1  package environment_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/onflow/atree"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/koko1123/flow-go-1/fvm/environment"
    10  	"github.com/koko1123/flow-go-1/fvm/errors"
    11  	"github.com/koko1123/flow-go-1/fvm/state"
    12  	"github.com/koko1123/flow-go-1/fvm/utils"
    13  	"github.com/koko1123/flow-go-1/model/flow"
    14  )
    15  
    16  func TestAccounts_Create(t *testing.T) {
    17  	t.Run("Sets registers", func(t *testing.T) {
    18  		view := utils.NewSimpleView()
    19  		txnState := state.NewTransactionState(view, state.DefaultParameters())
    20  		accounts := environment.NewAccounts(txnState)
    21  
    22  		address := flow.HexToAddress("01")
    23  
    24  		err := accounts.Create(nil, address)
    25  		require.NoError(t, err)
    26  
    27  		// account status
    28  		require.Equal(t, len(view.Ledger.RegisterTouches), 1)
    29  	})
    30  
    31  	t.Run("Fails if account exists", func(t *testing.T) {
    32  		view := utils.NewSimpleView()
    33  		txnState := state.NewTransactionState(view, state.DefaultParameters())
    34  		accounts := environment.NewAccounts(txnState)
    35  		address := flow.HexToAddress("01")
    36  
    37  		err := accounts.Create(nil, address)
    38  		require.NoError(t, err)
    39  
    40  		err = accounts.Create(nil, address)
    41  
    42  		require.Error(t, err)
    43  	})
    44  }
    45  
    46  func TestAccounts_GetWithNoKeys(t *testing.T) {
    47  	view := utils.NewSimpleView()
    48  	txnState := state.NewTransactionState(view, state.DefaultParameters())
    49  	accounts := environment.NewAccounts(txnState)
    50  	address := flow.HexToAddress("01")
    51  
    52  	err := accounts.Create(nil, address)
    53  	require.NoError(t, err)
    54  
    55  	require.NotPanics(t, func() {
    56  		_, _ = accounts.Get(address)
    57  	})
    58  }
    59  
    60  func TestAccounts_GetPublicKey(t *testing.T) {
    61  
    62  	t.Run("non-existent key index", func(t *testing.T) {
    63  
    64  		address := flow.HexToAddress("01")
    65  
    66  		for _, ledgerValue := range [][]byte{{}, nil} {
    67  
    68  			view := utils.NewSimpleView()
    69  
    70  			err := view.Set(
    71  				string(address.Bytes()),
    72  				"public_key_0",
    73  				ledgerValue,
    74  			)
    75  			require.NoError(t, err)
    76  
    77  			txnState := state.NewTransactionState(view, state.DefaultParameters())
    78  			accounts := environment.NewAccounts(txnState)
    79  
    80  			err = accounts.Create(nil, address)
    81  			require.NoError(t, err)
    82  
    83  			_, err = accounts.GetPublicKey(address, 0)
    84  			require.True(t, errors.IsAccountAccountPublicKeyNotFoundError(err))
    85  		}
    86  	})
    87  }
    88  
    89  func TestAccounts_GetPublicKeyCount(t *testing.T) {
    90  
    91  	t.Run("non-existent key count", func(t *testing.T) {
    92  
    93  		address := flow.HexToAddress("01")
    94  
    95  		for _, ledgerValue := range [][]byte{{}, nil} {
    96  
    97  			view := utils.NewSimpleView()
    98  			err := view.Set(
    99  				string(address.Bytes()),
   100  				"public_key_count",
   101  				ledgerValue,
   102  			)
   103  			require.NoError(t, err)
   104  
   105  			txnState := state.NewTransactionState(view, state.DefaultParameters())
   106  			accounts := environment.NewAccounts(txnState)
   107  
   108  			err = accounts.Create(nil, address)
   109  			require.NoError(t, err)
   110  
   111  			count, err := accounts.GetPublicKeyCount(address)
   112  			require.NoError(t, err)
   113  			require.Equal(t, uint64(0), count)
   114  		}
   115  	})
   116  }
   117  
   118  func TestAccounts_GetPublicKeys(t *testing.T) {
   119  
   120  	t.Run("non-existent key count", func(t *testing.T) {
   121  
   122  		address := flow.HexToAddress("01")
   123  
   124  		for _, ledgerValue := range [][]byte{{}, nil} {
   125  
   126  			view := utils.NewSimpleView()
   127  			err := view.Set(
   128  				string(address.Bytes()),
   129  				"public_key_count",
   130  				ledgerValue,
   131  			)
   132  			require.NoError(t, err)
   133  
   134  			txnState := state.NewTransactionState(view, state.DefaultParameters())
   135  			accounts := environment.NewAccounts(txnState)
   136  
   137  			err = accounts.Create(nil, address)
   138  			require.NoError(t, err)
   139  
   140  			keys, err := accounts.GetPublicKeys(address)
   141  			require.NoError(t, err)
   142  			require.Empty(t, keys)
   143  		}
   144  	})
   145  }
   146  
   147  // Some old account could be created without key count register
   148  // we recreate it in a test
   149  func TestAccounts_GetWithNoKeysCounter(t *testing.T) {
   150  	view := utils.NewSimpleView()
   151  
   152  	txnState := state.NewTransactionState(view, state.DefaultParameters())
   153  	accounts := environment.NewAccounts(txnState)
   154  	address := flow.HexToAddress("01")
   155  
   156  	err := accounts.Create(nil, address)
   157  	require.NoError(t, err)
   158  
   159  	err = view.Delete(
   160  		string(address.Bytes()),
   161  		"public_key_count")
   162  
   163  	require.NoError(t, err)
   164  
   165  	require.NotPanics(t, func() {
   166  		_, _ = accounts.Get(address)
   167  	})
   168  }
   169  
   170  func TestAccounts_SetContracts(t *testing.T) {
   171  
   172  	address := flow.HexToAddress("0x01")
   173  
   174  	t.Run("Setting a contract puts it in Contracts", func(t *testing.T) {
   175  		view := utils.NewSimpleView()
   176  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   177  		a := environment.NewAccounts(txnState)
   178  		err := a.Create(nil, address)
   179  		require.NoError(t, err)
   180  
   181  		err = a.SetContract("Dummy", address, []byte("non empty string"))
   182  		require.NoError(t, err)
   183  
   184  		contractNames, err := a.GetContractNames(address)
   185  		require.NoError(t, err)
   186  
   187  		require.Len(t, contractNames, 1, "There should only be one contract")
   188  		require.Equal(t, contractNames[0], "Dummy")
   189  	})
   190  	t.Run("Setting a contract again, does not add it to contracts", func(t *testing.T) {
   191  		view := utils.NewSimpleView()
   192  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   193  		a := environment.NewAccounts(txnState)
   194  		err := a.Create(nil, address)
   195  		require.NoError(t, err)
   196  
   197  		err = a.SetContract("Dummy", address, []byte("non empty string"))
   198  		require.NoError(t, err)
   199  
   200  		err = a.SetContract("Dummy", address, []byte("non empty string"))
   201  		require.NoError(t, err)
   202  
   203  		contractNames, err := a.GetContractNames(address)
   204  		require.NoError(t, err)
   205  
   206  		require.Len(t, contractNames, 1, "There should only be one contract")
   207  		require.Equal(t, contractNames[0], "Dummy")
   208  	})
   209  	t.Run("Setting more contracts always keeps them sorted", func(t *testing.T) {
   210  		view := utils.NewSimpleView()
   211  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   212  		a := environment.NewAccounts(txnState)
   213  		err := a.Create(nil, address)
   214  		require.NoError(t, err)
   215  
   216  		err = a.SetContract("Dummy", address, []byte("non empty string"))
   217  		require.NoError(t, err)
   218  
   219  		err = a.SetContract("ZedDummy", address, []byte("non empty string"))
   220  		require.NoError(t, err)
   221  
   222  		err = a.SetContract("ADummy", address, []byte("non empty string"))
   223  		require.NoError(t, err)
   224  
   225  		contractNames, err := a.GetContractNames(address)
   226  		require.NoError(t, err)
   227  
   228  		require.Len(t, contractNames, 3)
   229  		require.Equal(t, contractNames[0], "ADummy")
   230  		require.Equal(t, contractNames[1], "Dummy")
   231  		require.Equal(t, contractNames[2], "ZedDummy")
   232  	})
   233  	t.Run("Removing a contract does not fail if there is none", func(t *testing.T) {
   234  		view := utils.NewSimpleView()
   235  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   236  		a := environment.NewAccounts(txnState)
   237  		err := a.Create(nil, address)
   238  		require.NoError(t, err)
   239  
   240  		err = a.DeleteContract("Dummy", address)
   241  		require.NoError(t, err)
   242  	})
   243  	t.Run("Removing a contract removes it", func(t *testing.T) {
   244  		view := utils.NewSimpleView()
   245  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   246  		a := environment.NewAccounts(txnState)
   247  		err := a.Create(nil, address)
   248  		require.NoError(t, err)
   249  
   250  		err = a.SetContract("Dummy", address, []byte("non empty string"))
   251  		require.NoError(t, err)
   252  
   253  		err = a.DeleteContract("Dummy", address)
   254  		require.NoError(t, err)
   255  
   256  		contractNames, err := a.GetContractNames(address)
   257  		require.NoError(t, err)
   258  
   259  		require.Len(t, contractNames, 0, "There should be no contract")
   260  	})
   261  }
   262  
   263  func TestAccount_StorageUsed(t *testing.T) {
   264  
   265  	t.Run("Storage used on account creation is deterministic", func(t *testing.T) {
   266  		view := utils.NewSimpleView()
   267  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   268  		accounts := environment.NewAccounts(txnState)
   269  		address := flow.HexToAddress("01")
   270  
   271  		err := accounts.Create(nil, address)
   272  		require.NoError(t, err)
   273  
   274  		storageUsed, err := accounts.GetStorageUsed(address)
   275  		require.NoError(t, err)
   276  		require.Equal(t, uint64(40), storageUsed)
   277  	})
   278  
   279  	t.Run("Storage used on register set increases", func(t *testing.T) {
   280  		view := utils.NewSimpleView()
   281  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   282  		accounts := environment.NewAccounts(txnState)
   283  		address := flow.HexToAddress("01")
   284  
   285  		err := accounts.Create(nil, address)
   286  		require.NoError(t, err)
   287  
   288  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   289  		require.NoError(t, err)
   290  
   291  		storageUsed, err := accounts.GetStorageUsed(address)
   292  		require.NoError(t, err)
   293  		require.Equal(t, uint64(40+32), storageUsed)
   294  	})
   295  
   296  	t.Run("Storage used, set twice on same register to same value, stays the same", func(t *testing.T) {
   297  		view := utils.NewSimpleView()
   298  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   299  		accounts := environment.NewAccounts(txnState)
   300  		address := flow.HexToAddress("01")
   301  
   302  		err := accounts.Create(nil, address)
   303  		require.NoError(t, err)
   304  
   305  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   306  		require.NoError(t, err)
   307  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   308  		require.NoError(t, err)
   309  
   310  		storageUsed, err := accounts.GetStorageUsed(address)
   311  		require.NoError(t, err)
   312  		require.Equal(t, uint64(40+32), storageUsed)
   313  	})
   314  
   315  	t.Run("Storage used, set twice on same register to larger value, increases", func(t *testing.T) {
   316  		view := utils.NewSimpleView()
   317  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   318  		accounts := environment.NewAccounts(txnState)
   319  		address := flow.HexToAddress("01")
   320  
   321  		err := accounts.Create(nil, address)
   322  		require.NoError(t, err)
   323  
   324  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   325  		require.NoError(t, err)
   326  		err = accounts.SetValue(address, "some_key", createByteArray(13))
   327  		require.NoError(t, err)
   328  
   329  		storageUsed, err := accounts.GetStorageUsed(address)
   330  		require.NoError(t, err)
   331  		require.Equal(t, uint64(40+33), storageUsed)
   332  	})
   333  
   334  	t.Run("Storage used, set twice on same register to smaller value, decreases", func(t *testing.T) {
   335  		view := utils.NewSimpleView()
   336  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   337  		accounts := environment.NewAccounts(txnState)
   338  		address := flow.HexToAddress("01")
   339  
   340  		err := accounts.Create(nil, address)
   341  		require.NoError(t, err)
   342  
   343  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   344  		require.NoError(t, err)
   345  		err = accounts.SetValue(address, "some_key", createByteArray(11))
   346  		require.NoError(t, err)
   347  
   348  		storageUsed, err := accounts.GetStorageUsed(address)
   349  		require.NoError(t, err)
   350  		require.Equal(t, uint64(40+31), storageUsed)
   351  	})
   352  
   353  	t.Run("Storage used, after register deleted, decreases", func(t *testing.T) {
   354  		view := utils.NewSimpleView()
   355  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   356  		accounts := environment.NewAccounts(txnState)
   357  		address := flow.HexToAddress("01")
   358  
   359  		err := accounts.Create(nil, address)
   360  		require.NoError(t, err)
   361  
   362  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   363  		require.NoError(t, err)
   364  		err = accounts.SetValue(address, "some_key", nil)
   365  		require.NoError(t, err)
   366  
   367  		storageUsed, err := accounts.GetStorageUsed(address)
   368  		require.NoError(t, err)
   369  		require.Equal(t, uint64(40+0), storageUsed)
   370  	})
   371  
   372  	t.Run("Storage used on a complex scenario has correct value", func(t *testing.T) {
   373  		view := utils.NewSimpleView()
   374  		txnState := state.NewTransactionState(view, state.DefaultParameters())
   375  		accounts := environment.NewAccounts(txnState)
   376  		address := flow.HexToAddress("01")
   377  
   378  		err := accounts.Create(nil, address)
   379  		require.NoError(t, err)
   380  
   381  		err = accounts.SetValue(address, "some_key", createByteArray(12))
   382  		require.NoError(t, err)
   383  		err = accounts.SetValue(address, "some_key", createByteArray(11))
   384  		require.NoError(t, err)
   385  
   386  		err = accounts.SetValue(address, "some_key2", createByteArray(22))
   387  		require.NoError(t, err)
   388  		err = accounts.SetValue(address, "some_key2", createByteArray(23))
   389  		require.NoError(t, err)
   390  
   391  		err = accounts.SetValue(address, "some_key3", createByteArray(22))
   392  		require.NoError(t, err)
   393  		err = accounts.SetValue(address, "some_key3", createByteArray(0))
   394  		require.NoError(t, err)
   395  
   396  		storageUsed, err := accounts.GetStorageUsed(address)
   397  		require.NoError(t, err)
   398  		require.Equal(t, uint64(40+33+42), storageUsed)
   399  	})
   400  }
   401  
   402  func createByteArray(size int) []byte {
   403  	bytes := make([]byte, size)
   404  	for i := range bytes {
   405  		bytes[i] = 255
   406  	}
   407  	return bytes
   408  }
   409  
   410  func TestAccounts_AllocateStorageIndex(t *testing.T) {
   411  	view := utils.NewSimpleView()
   412  
   413  	txnState := state.NewTransactionState(view, state.DefaultParameters())
   414  	accounts := environment.NewAccounts(txnState)
   415  	address := flow.HexToAddress("01")
   416  
   417  	err := accounts.Create(nil, address)
   418  	require.NoError(t, err)
   419  
   420  	// no register set case
   421  	i, err := accounts.AllocateStorageIndex(address)
   422  	require.NoError(t, err)
   423  	require.Equal(t, i, atree.StorageIndex([8]byte{0, 0, 0, 0, 0, 0, 0, 1}))
   424  
   425  	// register already set case
   426  	i, err = accounts.AllocateStorageIndex(address)
   427  	require.NoError(t, err)
   428  	require.Equal(t, i, atree.StorageIndex([8]byte{0, 0, 0, 0, 0, 0, 0, 2}))
   429  
   430  	// register update successful
   431  	i, err = accounts.AllocateStorageIndex(address)
   432  	require.NoError(t, err)
   433  	require.Equal(t, i, atree.StorageIndex([8]byte{0, 0, 0, 0, 0, 0, 0, 3}))
   434  }