github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/keeper/statedb_mpt_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  
     6  	ethcmn "github.com/ethereum/go-ethereum/common"
     7  	ethcrypto "github.com/ethereum/go-ethereum/crypto"
     8  	"github.com/fibonacci-chain/fbc/x/evm/types"
     9  
    10  	ethermint "github.com/fibonacci-chain/fbc/app/types"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  )
    13  
    14  func (suite *KeeperMptTestSuite) TestCommitStateDB_CommitMpt() {
    15  	testCase := []struct {
    16  		name       string
    17  		malleate   func()
    18  		deleteObjs bool
    19  		expPass    bool
    20  	}{
    21  		{
    22  			"commit suicided",
    23  			func() {
    24  				ok := suite.stateDB.WithContext(suite.ctx).Suicide(suite.address)
    25  				suite.Require().True(ok)
    26  			},
    27  			true, true,
    28  		},
    29  		{
    30  			"commit with dirty value",
    31  			func() {
    32  				suite.stateDB.WithContext(suite.ctx).SetCode(suite.address, []byte("code"))
    33  			},
    34  			false, true,
    35  		},
    36  	}
    37  
    38  	for _, tc := range testCase {
    39  		tc.malleate()
    40  
    41  		hash, err := suite.stateDB.WithContext(suite.ctx).Commit(tc.deleteObjs)
    42  		suite.Require().Equal(ethcmn.Hash{}, hash)
    43  
    44  		if !tc.expPass {
    45  			suite.Require().Error(err, tc.name)
    46  			continue
    47  		}
    48  
    49  		suite.Require().NoError(err, tc.name)
    50  		acc := suite.app.AccountKeeper.GetAccount(suite.ctx, sdk.AccAddress(suite.address.Bytes()))
    51  
    52  		if tc.deleteObjs {
    53  			suite.Require().Nil(acc, tc.name)
    54  			continue
    55  		}
    56  
    57  		suite.Require().NotNil(acc, tc.name)
    58  		ethAcc, ok := acc.(*ethermint.EthAccount)
    59  		suite.Require().True(ok)
    60  		suite.Require().Equal(ethcrypto.Keccak256([]byte("code")), ethAcc.CodeHash)
    61  	}
    62  }
    63  
    64  func (suite *KeeperMptTestSuite) TestCommitStateDB_ForEachStorageMpt() {
    65  	var storage types.Storage
    66  
    67  	testCase := []struct {
    68  		name      string
    69  		malleate  func()
    70  		callback  func(key, value ethcmn.Hash) (stop bool)
    71  		expValues []ethcmn.Hash
    72  	}{
    73  		{
    74  			"aggregate state",
    75  			func() {
    76  				for i := 0; i < 5; i++ {
    77  					suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte(fmt.Sprintf("key%d", i))), ethcmn.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
    78  				}
    79  			},
    80  			func(key, value ethcmn.Hash) bool {
    81  				storage = append(storage, types.NewState(key, value))
    82  				return false
    83  			},
    84  			[]ethcmn.Hash{
    85  				ethcmn.BytesToHash([]byte("value0")),
    86  				ethcmn.BytesToHash([]byte("value1")),
    87  				ethcmn.BytesToHash([]byte("value2")),
    88  				ethcmn.BytesToHash([]byte("value3")),
    89  				ethcmn.BytesToHash([]byte("value4")),
    90  			},
    91  		},
    92  		{
    93  			"filter state",
    94  			func() {
    95  				suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value")))
    96  				suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte("filterkey")), ethcmn.BytesToHash([]byte("filtervalue")))
    97  			},
    98  			func(key, value ethcmn.Hash) bool {
    99  				if value == ethcmn.BytesToHash([]byte("filtervalue")) {
   100  					storage = append(storage, types.NewState(key, value))
   101  					return true
   102  				}
   103  				return false
   104  			},
   105  			[]ethcmn.Hash{
   106  				ethcmn.BytesToHash([]byte("filtervalue")),
   107  			},
   108  		},
   109  	}
   110  
   111  	for _, tc := range testCase {
   112  		suite.Run(tc.name, func() {
   113  			suite.SetupTest() // reset
   114  			tc.malleate()
   115  			suite.stateDB.WithContext(suite.ctx).Commit(false)
   116  
   117  			err := suite.stateDB.WithContext(suite.ctx).ForEachStorage(suite.address, tc.callback)
   118  			suite.Require().NoError(err)
   119  			suite.Require().Equal(len(tc.expValues), len(storage), fmt.Sprintf("Expected values:\n%v\nStorage Values\n%v", tc.expValues, storage))
   120  
   121  			vals := make([]ethcmn.Hash, len(storage))
   122  			for i := range storage {
   123  				vals[i] = storage[i].Value
   124  			}
   125  
   126  			suite.Require().ElementsMatch(tc.expValues, vals)
   127  		})
   128  		storage = types.Storage{}
   129  	}
   130  }
   131  
   132  func (suite *KeeperMptTestSuite) TestCommitStateDB_GetCommittedStateMpt() {
   133  	suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value")))
   134  	suite.stateDB.Commit(false)
   135  
   136  	hash := suite.stateDB.WithContext(suite.ctx).GetCommittedState(suite.address, ethcmn.BytesToHash([]byte("key")))
   137  	suite.Require().Equal(ethcmn.BytesToHash([]byte("value")), hash)
   138  }
   139  
   140  func (suite *KeeperMptTestSuite) TestCommitStateDB_GetStateByKeyMpt() {
   141  	suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value")))
   142  	suite.stateDB.Commit(false)
   143  
   144  	hash := suite.stateDB.WithContext(suite.ctx).GetStateByKeyMpt(suite.address, ethcmn.BytesToHash([]byte("key")))
   145  	suite.Require().Equal(ethcmn.BytesToHash([]byte("value")), hash)
   146  }
   147  
   148  func (suite *KeeperMptTestSuite) TestStateDB_CodeMpt() {
   149  	testCase := []struct {
   150  		name     string
   151  		address  ethcmn.Address
   152  		code     []byte
   153  		codeHash ethcmn.Hash
   154  		malleate func()
   155  	}{
   156  		{
   157  			"no stored code for state object",
   158  			suite.address,
   159  			nil,
   160  			ethcmn.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"),
   161  			func() {},
   162  		},
   163  		{
   164  			"existing address",
   165  			suite.address,
   166  			[]byte("code"),
   167  			ethcmn.HexToHash("0x2dc081a8d6d4714c79b5abd2e9b08c3a33b4ef1dcf946ef8b8cf6c495014f47b"),
   168  			func() {
   169  				suite.stateDB.WithContext(suite.ctx).SetCode(suite.address, []byte("code"))
   170  				suite.stateDB.Commit(false)
   171  			},
   172  		},
   173  		{
   174  			"state object not found",
   175  			ethcmn.Address{},
   176  			nil,
   177  			ethcmn.HexToHash("0"),
   178  			func() {},
   179  		},
   180  	}
   181  
   182  	for _, tc := range testCase {
   183  		tc.malleate()
   184  
   185  		suite.Require().Equal(tc.code, suite.stateDB.WithContext(suite.ctx).GetCode(tc.address), tc.name)
   186  		suite.Require().Equal(len(tc.code), suite.stateDB.WithContext(suite.ctx).GetCodeSize(tc.address), tc.name)
   187  		suite.Require().Equal(tc.codeHash, suite.stateDB.WithContext(suite.ctx).GetCodeHash(tc.address), tc.name)
   188  		suite.Require().Equal(tc.code, suite.stateDB.WithContext(suite.ctx).GetCodeByHashInRawDB(tc.codeHash), tc.name)
   189  	}
   190  }
   191  
   192  func (suite *KeeperMptTestSuite) TestStateDB_StateMpt() {
   193  	key := ethcmn.BytesToHash([]byte("foo"))
   194  	val := ethcmn.BytesToHash([]byte("bar"))
   195  	suite.stateDB.WithContext(suite.ctx).SetState(suite.address, key, val)
   196  
   197  	testCase := []struct {
   198  		name    string
   199  		address ethcmn.Address
   200  		key     ethcmn.Hash
   201  		value   ethcmn.Hash
   202  	}{
   203  		{
   204  			"found state",
   205  			suite.address,
   206  			ethcmn.BytesToHash([]byte("foo")),
   207  			ethcmn.BytesToHash([]byte("bar")),
   208  		},
   209  		{
   210  			"state not found",
   211  			suite.address,
   212  			ethcmn.BytesToHash([]byte("key")),
   213  			ethcmn.Hash{},
   214  		},
   215  		{
   216  			"object not found",
   217  			ethcmn.Address{},
   218  			ethcmn.BytesToHash([]byte("foo")),
   219  			ethcmn.Hash{},
   220  		},
   221  	}
   222  	for _, tc := range testCase {
   223  		value := suite.stateDB.WithContext(suite.ctx).GetState(tc.address, tc.key)
   224  		suite.Require().Equal(tc.value, value, tc.name)
   225  	}
   226  }
   227  
   228  func (suite *KeeperMptTestSuite) TestStorageTrieMpt() {
   229  	for i := 0; i < 5; i++ {
   230  		suite.stateDB.WithContext(suite.ctx).SetState(suite.address, ethcmn.BytesToHash([]byte(fmt.Sprintf("key%d", i))), ethcmn.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
   231  	}
   232  
   233  	trie := suite.stateDB.WithContext(suite.ctx).StorageTrie(suite.address)
   234  	suite.Require().NotNil(trie, "Ethermint now use a direct storage trie.")
   235  }