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 }