github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/statedb_test.go (about) 1 package types_test 2 3 import ( 4 "fmt" 5 "math/big" 6 "testing" 7 8 ethcmn "github.com/ethereum/go-ethereum/common" 9 ethtypes "github.com/ethereum/go-ethereum/core/types" 10 ethcrypto "github.com/ethereum/go-ethereum/crypto" 11 "github.com/fibonacci-chain/fbc/app" 12 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 13 ethermint "github.com/fibonacci-chain/fbc/app/types" 14 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 16 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 17 "github.com/fibonacci-chain/fbc/x/evm/types" 18 "github.com/stretchr/testify/suite" 19 ) 20 21 type StateDBTestSuite struct { 22 suite.Suite 23 24 ctx sdk.Context 25 app *app.FBChainApp 26 stateDB *types.CommitStateDB 27 address ethcmn.Address 28 stateObject types.StateObject 29 } 30 31 func TestStateDBTestSuite(t *testing.T) { 32 suite.Run(t, new(StateDBTestSuite)) 33 } 34 35 func (suite *StateDBTestSuite) SetupTest() { 36 checkTx := false 37 38 suite.app = app.Setup(checkTx) 39 suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-1"}) 40 suite.ctx.SetDeliver() 41 suite.stateDB = types.CreateEmptyCommitStateDB(suite.app.EvmKeeper.GenerateCSDBParams(), suite.ctx) 42 43 privkey, err := ethsecp256k1.GenerateKey() 44 suite.Require().NoError(err) 45 46 suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes()) 47 48 balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.ZeroInt())) 49 acc := ðermint.EthAccount{ 50 BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0), 51 CodeHash: ethcrypto.Keccak256(nil), 52 } 53 54 suite.app.AccountKeeper.SetAccount(suite.ctx, acc) 55 suite.stateObject = suite.stateDB.GetOrNewStateObject(suite.address) 56 params := types.DefaultParams() 57 params.EnableCreate = true 58 params.EnableCall = true 59 suite.stateDB.SetParams(params) 60 } 61 62 func (suite *StateDBTestSuite) TestParams() { 63 defaultParams := types.DefaultParams() 64 defaultParams.EnableCreate = true 65 defaultParams.EnableCall = true 66 params := suite.stateDB.GetParams() 67 suite.Require().Equal(defaultParams, params) 68 suite.stateDB.SetParams(params) 69 newParams := suite.stateDB.GetParams() 70 suite.Require().Equal(newParams, params) 71 } 72 73 func (suite *StateDBTestSuite) TestGetHeightHash() { 74 hash := suite.stateDB.GetHeightHash(0) 75 suite.Require().Equal(ethcmn.Hash{}.String(), hash.String()) 76 77 expHash := ethcmn.BytesToHash([]byte("hash")) 78 suite.stateDB.SetHeightHash(10, expHash) 79 80 hash = suite.stateDB.GetHeightHash(10) 81 suite.Require().Equal(expHash.String(), hash.String()) 82 } 83 84 func (suite *StateDBTestSuite) TestBloomFilter() { 85 // Prepare db for logs 86 tHash := ethcmn.BytesToHash([]byte{0x1}) 87 bhash := ethcmn.BytesToHash([]byte{0x1}) 88 suite.stateDB.Prepare(tHash, bhash, 0) 89 contractAddress := ethcmn.BigToAddress(big.NewInt(1)) 90 log := ethtypes.Log{Address: contractAddress} 91 92 testCase := []struct { 93 name string 94 malleate func() 95 numLogs int 96 isBloom bool 97 }{ 98 { 99 "no logs", 100 func() {}, 101 0, 102 false, 103 }, 104 { 105 "add log", 106 func() { 107 suite.stateDB.AddLog(&log) 108 }, 109 1, 110 false, 111 }, 112 { 113 "bloom", 114 func() {}, 115 0, 116 true, 117 }, 118 } 119 120 for _, tc := range testCase { 121 tc.malleate() 122 logs, err := suite.stateDB.GetLogs(tHash) 123 suite.Require().NoError(err) 124 if !tc.isBloom { 125 suite.Require().Len(logs, tc.numLogs, tc.name) 126 if len(logs) != 0 { 127 suite.Require().Equal(log, *logs[0], tc.name) 128 } 129 } else { 130 // get logs bloom from the log 131 bloomBytes := ethtypes.LogsBloom(logs) 132 bloomFilter := ethtypes.BytesToBloom(bloomBytes) 133 suite.Require().True(ethtypes.BloomLookup(bloomFilter, contractAddress), tc.name) 134 suite.Require().False(ethtypes.BloomLookup(bloomFilter, ethcmn.BigToAddress(big.NewInt(2))), tc.name) 135 } 136 } 137 } 138 139 func (suite *StateDBTestSuite) TestStateDB_Balance() { 140 testCase := []struct { 141 name string 142 malleate func() 143 balance *big.Int 144 }{ 145 { 146 "set balance", 147 func() { 148 suite.stateDB.SetBalance(suite.address, big.NewInt(100)) 149 }, 150 big.NewInt(100), 151 }, 152 { 153 "sub balance", 154 func() { 155 suite.stateDB.SubBalance(suite.address, big.NewInt(100)) 156 }, 157 big.NewInt(0), 158 }, 159 { 160 "add balance", 161 func() { 162 suite.stateDB.AddBalance(suite.address, big.NewInt(200)) 163 }, 164 big.NewInt(200), 165 }, 166 } 167 168 for _, tc := range testCase { 169 tc.malleate() 170 suite.Require().Equal(tc.balance, suite.stateDB.GetBalance(suite.address), tc.name) 171 } 172 } 173 174 func (suite *StateDBTestSuite) TestStateDBNonce() { 175 nonce := uint64(123) 176 suite.stateDB.SetNonce(suite.address, nonce) 177 suite.Require().Equal(nonce, suite.stateDB.GetNonce(suite.address)) 178 } 179 180 func (suite *StateDBTestSuite) TestStateDB_Error() { 181 nonce := suite.stateDB.GetNonce(ethcmn.Address{}) 182 suite.Require().Equal(0, int(nonce)) 183 suite.Require().Error(suite.stateDB.Error()) 184 } 185 186 func (suite *StateDBTestSuite) TestStateDB_Database() { 187 suite.Require().NotNil(suite.stateDB.Database()) 188 } 189 190 func (suite *StateDBTestSuite) TestStateDB_State() { 191 key := ethcmn.BytesToHash([]byte("foo")) 192 val := ethcmn.BytesToHash([]byte("bar")) 193 suite.stateDB.SetState(suite.address, key, val) 194 195 testCase := []struct { 196 name string 197 address ethcmn.Address 198 key ethcmn.Hash 199 value ethcmn.Hash 200 }{ 201 { 202 "found state", 203 suite.address, 204 ethcmn.BytesToHash([]byte("foo")), 205 ethcmn.BytesToHash([]byte("bar")), 206 }, 207 { 208 "state not found", 209 suite.address, 210 ethcmn.BytesToHash([]byte("key")), 211 ethcmn.Hash{}, 212 }, 213 { 214 "object not found", 215 ethcmn.Address{}, 216 ethcmn.BytesToHash([]byte("foo")), 217 ethcmn.Hash{}, 218 }, 219 } 220 for _, tc := range testCase { 221 value := suite.stateDB.GetState(tc.address, tc.key) 222 suite.Require().Equal(tc.value, value, tc.name) 223 } 224 } 225 226 func (suite *StateDBTestSuite) TestStateDB_Code() { 227 testCase := []struct { 228 name string 229 address ethcmn.Address 230 code []byte 231 malleate func() 232 }{ 233 { 234 "no stored code for state object", 235 suite.address, 236 nil, 237 func() {}, 238 }, 239 { 240 "existing address", 241 suite.address, 242 []byte("code"), 243 func() { 244 suite.stateDB.SetCode(suite.address, []byte("code")) 245 }, 246 }, 247 { 248 "state object not found", 249 ethcmn.Address{}, 250 nil, 251 func() {}, 252 }, 253 } 254 255 for _, tc := range testCase { 256 tc.malleate() 257 258 suite.Require().Equal(tc.code, suite.stateDB.GetCode(tc.address), tc.name) 259 suite.Require().Equal(len(tc.code), suite.stateDB.GetCodeSize(tc.address), tc.name) 260 } 261 } 262 263 func (suite *StateDBTestSuite) TestStateDB_Logs() { 264 txhash := ethcmn.BytesToHash([]byte("topic")) 265 testCase := []struct { 266 name string 267 log ethtypes.Log 268 }{ 269 { 270 "state db log", 271 ethtypes.Log{ 272 Address: suite.address, 273 Topics: []ethcmn.Hash{txhash}, 274 Data: []byte("data"), 275 BlockNumber: 1, 276 TxHash: txhash, 277 TxIndex: 1, 278 BlockHash: ethcmn.Hash{}, 279 Index: 1, 280 Removed: false, 281 }, 282 }, 283 } 284 285 for _, tc := range testCase { 286 hash := ethcmn.BytesToHash([]byte("hash")) 287 logs := []*ethtypes.Log{&tc.log} 288 289 suite.stateDB.SetLogs(txhash, logs) 290 dbLogs, err := suite.stateDB.GetLogs(txhash) 291 suite.Require().NoError(err) 292 suite.Require().Equal(logs, dbLogs, tc.name) 293 294 suite.stateDB.DeleteLogs(txhash) 295 dbLogs, err = suite.stateDB.GetLogs(txhash) 296 suite.Require().NoError(err) 297 suite.Require().Empty(dbLogs, tc.name) 298 299 suite.stateDB.Prepare(hash, ethcmn.BytesToHash([]byte("bhash")), 1) 300 suite.stateDB.AddLog(&tc.log) 301 newLogs, err := suite.stateDB.GetLogs(hash) 302 suite.Require().NoError(err) 303 suite.Require().Equal(logs, newLogs, tc.name) 304 305 //resets state but checking to see if storekey still persists. 306 suite.stateDB.Reset(hash) 307 newLogs, err = suite.stateDB.GetLogs(hash) 308 suite.Require().NoError(err) 309 suite.Require().Equal(logs, newLogs, tc.name) 310 } 311 } 312 313 func (suite *StateDBTestSuite) TestStateDB_Preimage() { 314 hash := ethcmn.BytesToHash([]byte("hash")) 315 preimage := []byte("preimage") 316 317 suite.stateDB.AddPreimage(hash, preimage) 318 suite.Require().Equal(preimage, suite.stateDB.Preimages()[hash]) 319 } 320 321 func (suite *StateDBTestSuite) TestStateDB_Refund() { 322 testCase := []struct { 323 name string 324 addAmount uint64 325 subAmount uint64 326 expRefund uint64 327 expPanic bool 328 }{ 329 { 330 "refund 0", 331 0, 0, 0, 332 false, 333 }, 334 { 335 "refund positive amount", 336 100, 0, 100, 337 false, 338 }, 339 { 340 "refund panic", 341 100, 200, 100, 342 true, 343 }, 344 } 345 346 for _, tc := range testCase { 347 suite.Run(tc.name, func() { 348 suite.SetupTest() // reset 349 350 suite.stateDB.AddRefund(tc.addAmount) 351 suite.Require().Equal(tc.addAmount, suite.stateDB.GetRefund()) 352 353 if tc.expPanic { 354 suite.Panics(func() { 355 suite.stateDB.SubRefund(tc.subAmount) 356 }) 357 } else { 358 suite.stateDB.SubRefund(tc.subAmount) 359 suite.Require().Equal(tc.expRefund, suite.stateDB.GetRefund()) 360 } 361 }) 362 } 363 } 364 365 func (suite *StateDBTestSuite) TestStateDB_CreateAccount() { 366 prevBalance := big.NewInt(12) 367 368 testCase := []struct { 369 name string 370 address ethcmn.Address 371 malleate func() 372 }{ 373 { 374 "existing account", 375 suite.address, 376 func() { 377 suite.stateDB.AddBalance(suite.address, prevBalance) 378 }, 379 }, 380 { 381 "new account", 382 ethcmn.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b4c1"), 383 func() { 384 prevBalance = big.NewInt(0) 385 }, 386 }, 387 } 388 389 for _, tc := range testCase { 390 tc.malleate() 391 392 suite.stateDB.CreateAccount(tc.address) 393 suite.Require().True(suite.stateDB.Exist(tc.address), tc.name) 394 suite.Require().Equal(prevBalance, suite.stateDB.GetBalance(tc.address), tc.name) 395 } 396 } 397 398 func (suite *StateDBTestSuite) TestStateDB_ClearStateObj() { 399 priv, err := ethsecp256k1.GenerateKey() 400 suite.Require().NoError(err) 401 402 addr := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey) 403 404 suite.stateDB.CreateAccount(addr) 405 suite.Require().True(suite.stateDB.Exist(addr)) 406 407 suite.stateDB.ClearStateObjects() 408 suite.Require().False(suite.stateDB.Exist(addr)) 409 } 410 411 func (suite *StateDBTestSuite) TestStateDB_Reset() { 412 priv, err := ethsecp256k1.GenerateKey() 413 suite.Require().NoError(err) 414 415 addr := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey) 416 417 suite.stateDB.CreateAccount(addr) 418 suite.Require().True(suite.stateDB.Exist(addr)) 419 420 err = suite.stateDB.Reset(ethcmn.BytesToHash(nil)) 421 suite.Require().NoError(err) 422 suite.Require().False(suite.stateDB.Exist(addr)) 423 } 424 425 func (suite *StateDBTestSuite) TestSuiteDB_Prepare() { 426 thash := ethcmn.BytesToHash([]byte("thash")) 427 bhash := ethcmn.BytesToHash([]byte("bhash")) 428 txi := 1 429 430 suite.stateDB.Prepare(thash, bhash, txi) 431 suite.stateDB.SetBlockHash(bhash) 432 433 suite.Require().Equal(txi, suite.stateDB.TxIndex()) 434 suite.Require().Equal(bhash, suite.stateDB.BlockHash()) 435 } 436 437 func (suite *StateDBTestSuite) TestSuiteDB_Empty() { 438 suite.Require().True(suite.stateDB.Empty(suite.address)) 439 440 suite.stateDB.SetBalance(suite.address, big.NewInt(100)) 441 suite.Require().False(suite.stateDB.Empty(suite.address)) 442 } 443 444 func (suite *StateDBTestSuite) TestSuiteDB_Suicide() { 445 testCase := []struct { 446 name string 447 amount *big.Int 448 expPass bool 449 delete bool 450 }{ 451 { 452 "suicide zero balance", 453 big.NewInt(0), 454 false, false, 455 }, 456 { 457 "suicide with balance", 458 big.NewInt(100), 459 true, false, 460 }, 461 { 462 "delete", 463 big.NewInt(0), 464 true, true, 465 }, 466 } 467 468 for _, tc := range testCase { 469 if tc.delete { 470 _, err := suite.stateDB.Commit(tc.delete) 471 suite.Require().NoError(err, tc.name) 472 suite.Require().False(suite.stateDB.Exist(suite.address), tc.name) 473 continue 474 } 475 476 if tc.expPass { 477 suite.stateDB.SetBalance(suite.address, tc.amount) 478 suicide := suite.stateDB.Suicide(suite.address) 479 suite.Require().True(suicide, tc.name) 480 suite.Require().True(suite.stateDB.HasSuicided(suite.address), tc.name) 481 } else { 482 //Suicide only works for an account with non-zero balance/nonce 483 priv, err := ethsecp256k1.GenerateKey() 484 suite.Require().NoError(err) 485 486 addr := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey) 487 suicide := suite.stateDB.Suicide(addr) 488 suite.Require().False(suicide, tc.name) 489 suite.Require().False(suite.stateDB.HasSuicided(addr), tc.name) 490 } 491 } 492 } 493 494 func (suite *StateDBTestSuite) TestCommitStateDB_Commit() { 495 testCase := []struct { 496 name string 497 malleate func() 498 deleteObjs bool 499 expPass bool 500 }{ 501 { 502 "commit suicided", 503 func() { 504 ok := suite.stateDB.Suicide(suite.address) 505 suite.Require().True(ok) 506 }, 507 true, true, 508 }, 509 { 510 "commit with dirty value", 511 func() { 512 suite.stateDB.SetCode(suite.address, []byte("code")) 513 }, 514 false, true, 515 }, 516 } 517 518 for _, tc := range testCase { 519 tc.malleate() 520 521 hash, err := suite.stateDB.Commit(tc.deleteObjs) 522 suite.Require().Equal(ethcmn.Hash{}, hash) 523 524 if !tc.expPass { 525 suite.Require().Error(err, tc.name) 526 continue 527 } 528 529 suite.Require().NoError(err, tc.name) 530 acc := suite.app.AccountKeeper.GetAccount(suite.ctx, sdk.AccAddress(suite.address.Bytes())) 531 532 if tc.deleteObjs { 533 suite.Require().Nil(acc, tc.name) 534 continue 535 } 536 537 suite.Require().NotNil(acc, tc.name) 538 ethAcc, ok := acc.(*ethermint.EthAccount) 539 suite.Require().True(ok) 540 suite.Require().Equal(ethcrypto.Keccak256([]byte("code")), ethAcc.CodeHash) 541 } 542 } 543 544 func (suite *StateDBTestSuite) TestCommitStateDB_Finalize() { 545 testCase := []struct { 546 name string 547 malleate func() 548 deleteObjs bool 549 expPass bool 550 }{ 551 { 552 "finalize suicided", 553 func() { 554 ok := suite.stateDB.Suicide(suite.address) 555 suite.Require().True(ok) 556 }, 557 true, true, 558 }, 559 { 560 "finalize, not suicided", 561 func() { 562 suite.stateDB.AddBalance(suite.address, big.NewInt(5)) 563 }, 564 false, true, 565 }, 566 { 567 "finalize, dirty storage", 568 func() { 569 suite.stateDB.SetState(suite.address, ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value"))) 570 }, 571 false, true, 572 }, 573 } 574 575 for _, tc := range testCase { 576 tc.malleate() 577 578 suite.stateDB.IntermediateRoot(tc.deleteObjs) 579 580 if !tc.expPass { 581 hash := suite.stateDB.GetCommittedState(suite.address, ethcmn.BytesToHash([]byte("key"))) 582 suite.Require().NotEqual(ethcmn.Hash{}, hash, tc.name) 583 continue 584 } 585 586 acc := suite.app.AccountKeeper.GetAccount(suite.ctx, sdk.AccAddress(suite.address.Bytes())) 587 588 if tc.deleteObjs { 589 suite.Require().Nil(acc, tc.name) 590 continue 591 } 592 593 suite.Require().NotNil(acc, tc.name) 594 } 595 } 596 func (suite *StateDBTestSuite) TestCommitStateDB_GetCommittedState() { 597 hash := suite.stateDB.GetCommittedState(ethcmn.Address{}, ethcmn.BytesToHash([]byte("key"))) 598 suite.Require().Equal(ethcmn.Hash{}, hash) 599 } 600 601 func (suite *StateDBTestSuite) TestCommitStateDB_Snapshot() { 602 id := suite.stateDB.Snapshot() 603 suite.Require().NotPanics(func() { 604 suite.stateDB.RevertToSnapshot(id) 605 }) 606 607 suite.Require().Panics(func() { 608 suite.stateDB.RevertToSnapshot(-1) 609 }, "invalid revision should panic") 610 } 611 612 func (suite *StateDBTestSuite) TestCommitStateDB_ForEachStorage() { 613 var storage types.Storage 614 615 testCase := []struct { 616 name string 617 malleate func() 618 callback func(key, value ethcmn.Hash) (stop bool) 619 expValues []ethcmn.Hash 620 }{ 621 { 622 "aggregate state", 623 func() { 624 for i := 0; i < 5; i++ { 625 suite.stateDB.SetState(suite.address, ethcmn.BytesToHash([]byte(fmt.Sprintf("key%d", i))), ethcmn.BytesToHash([]byte(fmt.Sprintf("value%d", i)))) 626 } 627 }, 628 func(key, value ethcmn.Hash) bool { 629 storage = append(storage, types.NewState(key, value)) 630 return false 631 }, 632 []ethcmn.Hash{ 633 ethcmn.BytesToHash([]byte("value0")), 634 ethcmn.BytesToHash([]byte("value1")), 635 ethcmn.BytesToHash([]byte("value2")), 636 ethcmn.BytesToHash([]byte("value3")), 637 ethcmn.BytesToHash([]byte("value4")), 638 }, 639 }, 640 { 641 "filter state", 642 func() { 643 suite.stateDB.SetState(suite.address, ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value"))) 644 suite.stateDB.SetState(suite.address, ethcmn.BytesToHash([]byte("filterkey")), ethcmn.BytesToHash([]byte("filtervalue"))) 645 }, 646 func(key, value ethcmn.Hash) bool { 647 if value == ethcmn.BytesToHash([]byte("filtervalue")) { 648 storage = append(storage, types.NewState(key, value)) 649 return true 650 } 651 return false 652 }, 653 []ethcmn.Hash{ 654 ethcmn.BytesToHash([]byte("filtervalue")), 655 }, 656 }, 657 } 658 659 for _, tc := range testCase { 660 suite.Run(tc.name, func() { 661 suite.SetupTest() // reset 662 tc.malleate() 663 suite.stateDB.Commit(false) 664 665 err := suite.stateDB.ForEachStorage(suite.address, tc.callback) 666 suite.Require().NoError(err) 667 suite.Require().Equal(len(tc.expValues), len(storage), fmt.Sprintf("Expected values:\n%v\nStorage Values\n%v", tc.expValues, storage)) 668 669 vals := make([]ethcmn.Hash, len(storage)) 670 for i := range storage { 671 vals[i] = storage[i].Value 672 } 673 674 suite.Require().ElementsMatch(tc.expValues, vals) 675 }) 676 storage = types.Storage{} 677 } 678 } 679 680 func (suite *StateDBTestSuite) TestCommitStateDB_AccessList() { 681 addr := ethcmn.Address([20]byte{77}) 682 hash := ethcmn.Hash([32]byte{99}) 683 684 suite.Require().False(suite.stateDB.AddressInAccessList(addr)) 685 686 suite.stateDB.AddAddressToAccessList(addr) 687 suite.Require().True(suite.stateDB.AddressInAccessList(addr)) 688 addrIn, slotIn := suite.stateDB.SlotInAccessList(addr, hash) 689 suite.Require().True(addrIn) 690 suite.Require().False(slotIn) 691 692 suite.stateDB.AddSlotToAccessList(addr, hash) 693 addrIn, slotIn = suite.stateDB.SlotInAccessList(addr, hash) 694 suite.Require().True(addrIn) 695 suite.Require().True(slotIn) 696 } 697 698 func (suite *StateDBTestSuite) TestCommitStateDB_ContractDeploymentWhitelist() { 699 // create addresses for test 700 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 701 addr2 := ethcmn.BytesToAddress([]byte{0x1}).Bytes() 702 703 testCase := []struct { 704 name string 705 targetAddrList types.AddressList 706 // true -> add, false -> delete 707 isAdded bool 708 expectedLen int 709 }{ 710 { 711 "add empty list into whitelist", 712 types.AddressList{}, 713 true, 714 0, 715 }, 716 { 717 "add list with one member into whitelist", 718 types.AddressList{addr1}, 719 true, 720 1, 721 }, 722 { 723 "add list with two members into the whitelist that has contained one member already", 724 types.AddressList{addr1, addr2}, 725 true, 726 2, 727 }, 728 { 729 "delete empty from whitelist", 730 types.AddressList{}, 731 false, 732 2, 733 }, 734 { 735 "delete list with one member from whitelist", 736 types.AddressList{addr1}, 737 false, 738 1, 739 }, 740 { 741 "delete list with two members from the whitelist that has contained one member only", 742 types.AddressList{addr1, addr2}, 743 false, 744 0, 745 }, 746 { 747 "delete list with two members from the empty whitelist", 748 types.AddressList{addr1, addr2}, 749 false, 750 0, 751 }, 752 } 753 754 for _, tc := range testCase { 755 suite.Run(tc.name, func() { 756 if tc.isAdded { 757 suite.stateDB.SetContractDeploymentWhitelist(tc.targetAddrList) 758 } else { 759 suite.stateDB.DeleteContractDeploymentWhitelist(tc.targetAddrList) 760 } 761 762 whitelist := suite.stateDB.GetContractDeploymentWhitelist() 763 suite.Require().Equal(tc.expectedLen, len(whitelist)) 764 }) 765 } 766 } 767 768 func (suite *StateDBTestSuite) TestCommitStateDB_ContractBlockedList() { 769 // create addresses for test 770 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 771 addr2 := ethcmn.BytesToAddress([]byte{0x1}).Bytes() 772 773 testCase := []struct { 774 name string 775 targetAddrList types.AddressList 776 // true -> add, false -> delete 777 isAdded bool 778 expectedLen int 779 }{ 780 { 781 "add empty list into blocked list", 782 types.AddressList{}, 783 true, 784 0, 785 }, 786 { 787 "add list with one member into blocked list", 788 types.AddressList{addr1}, 789 true, 790 1, 791 }, 792 { 793 "add list with two members into the blocked list that has contained one member already", 794 types.AddressList{addr1, addr2}, 795 true, 796 2, 797 }, 798 { 799 "delete empty from blocked list", 800 types.AddressList{}, 801 false, 802 2, 803 }, 804 { 805 "delete list with one member from blocked list", 806 types.AddressList{addr1}, 807 false, 808 1, 809 }, 810 { 811 "delete list with two members from the blocked list that has contained one member only", 812 types.AddressList{addr1, addr2}, 813 false, 814 0, 815 }, 816 { 817 "delete list with two members from the empty blocked list", 818 types.AddressList{addr1, addr2}, 819 false, 820 0, 821 }, 822 } 823 824 for _, tc := range testCase { 825 suite.Run(tc.name, func() { 826 if tc.isAdded { 827 suite.stateDB.SetContractBlockedList(tc.targetAddrList) 828 } else { 829 suite.stateDB.DeleteContractBlockedList(tc.targetAddrList) 830 } 831 832 blockedList := suite.stateDB.GetContractBlockedList() 833 suite.Require().Equal(tc.expectedLen, len(blockedList)) 834 }) 835 } 836 } 837 838 func (suite *StateDBTestSuite) TestCommitStateDB_ContractMethodBlockedList() { 839 // create addresses for test 840 bcMethodOne1 := types.BlockedContract{ 841 Address: ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 842 BlockMethods: types.ContractMethods{ 843 types.ContractMethod{ 844 Sign: "aaaa", 845 Extra: "aaaa()", 846 }, 847 }, 848 } 849 bcMethodTwo1 := types.BlockedContract{ 850 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 851 BlockMethods: types.ContractMethods{ 852 types.ContractMethod{ 853 Sign: "aaaa", 854 Extra: "aaaa()", 855 }, 856 }, 857 } 858 859 bcMethodOne3 := types.BlockedContract{ 860 Address: bcMethodOne1.Address, 861 BlockMethods: types.ContractMethods{ 862 types.ContractMethod{ 863 Sign: "bbbb", 864 Extra: "bbbb()", 865 }, 866 }, 867 } 868 methods := types.ContractMethods{} 869 methods = append(methods, bcMethodOne1.BlockMethods...) 870 methods = append(methods, bcMethodOne3.BlockMethods...) 871 expectBcMethodOne3 := types.NewBlockContract(bcMethodOne1.Address, methods) 872 873 bcMethodOne4 := types.BlockedContract{ 874 Address: bcMethodOne1.Address, 875 BlockMethods: types.ContractMethods{ 876 types.ContractMethod{ 877 Sign: "bbbb", 878 Extra: "bbbb()", 879 }, 880 types.ContractMethod{ 881 Sign: "cccc", 882 Extra: "cccc()", 883 }, 884 }, 885 } 886 methods = types.ContractMethods{} 887 methods = append(methods, bcMethodOne1.BlockMethods...) 888 methods = append(methods, bcMethodOne4.BlockMethods...) 889 expectBcMethodOne4 := types.NewBlockContract(bcMethodOne1.Address, methods) 890 891 bcMethodOne5 := types.BlockedContract{ 892 Address: bcMethodOne1.Address, 893 BlockMethods: types.ContractMethods{ 894 types.ContractMethod{ 895 Sign: "bbbb", 896 Extra: "bbbb()", 897 }, 898 types.ContractMethod{ 899 Sign: "cccc", 900 Extra: "cccc()", 901 }, 902 types.ContractMethod{ 903 Sign: "dddd", 904 Extra: "dddd()", 905 }, 906 }, 907 } 908 909 testCase := []struct { 910 name string 911 targetAddrList types.BlockedContractList 912 // true -> add, false -> delete 913 isAdded bool 914 expectedLen int 915 expectedContractList types.BlockedContractList 916 success bool 917 }{ 918 { 919 "add empty blocked contract list", 920 types.BlockedContractList{}, 921 true, 922 0, 923 nil, 924 true, 925 }, 926 { 927 "add list with one member into blocked list", 928 types.BlockedContractList{bcMethodOne1}, 929 true, 930 1, 931 types.BlockedContractList{bcMethodOne1}, 932 true, 933 }, 934 { 935 "add list with two members into the blocked list that has contained one member already", 936 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 937 true, 938 2, 939 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 940 true, 941 }, 942 { 943 "add list with one members(method empty) into the blocked list that has contained one member already", 944 types.BlockedContractList{bcMethodOne1}, 945 true, 946 2, 947 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 948 true, 949 }, 950 { 951 "delete empty from blocked list", 952 types.BlockedContractList{}, 953 false, 954 2, 955 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 956 true, 957 }, 958 { 959 "delete list with one members from the blocked list that has contained one member only", 960 types.BlockedContractList{bcMethodTwo1}, 961 false, 962 1, 963 types.BlockedContractList{bcMethodOne1}, 964 true, 965 }, 966 { 967 "delete list with two members from the empty blocked list", 968 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 969 false, 970 0, 971 nil, 972 false, 973 }, 974 { 975 "reset contract method blocked list", 976 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 977 true, 978 2, 979 types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, 980 true, 981 }, 982 { 983 "add new method into contract method blocked list", 984 types.BlockedContractList{bcMethodOne3}, 985 true, 986 2, 987 types.BlockedContractList{*expectBcMethodOne3, bcMethodTwo1}, 988 true, 989 }, 990 { 991 "add new methods which is one method exist into contract method blocked list", 992 types.BlockedContractList{bcMethodOne4}, 993 true, 994 2, 995 types.BlockedContractList{*expectBcMethodOne4, bcMethodTwo1}, 996 true, 997 }, 998 { 999 "delete methods which is not exist from contract method blocked list", 1000 types.BlockedContractList{bcMethodOne5}, 1001 false, 1002 2, 1003 types.BlockedContractList{*expectBcMethodOne4, bcMethodTwo1}, 1004 false, 1005 }, 1006 { 1007 "delete all methods from contract method blocked list", 1008 types.BlockedContractList{*expectBcMethodOne4}, 1009 false, 1010 1, 1011 types.BlockedContractList{bcMethodTwo1}, 1012 true, 1013 }, 1014 } 1015 1016 for _, tc := range testCase { 1017 suite.Run(tc.name, func() { 1018 var err sdk.Error 1019 if tc.isAdded { 1020 err = suite.stateDB.InsertContractMethodBlockedList(tc.targetAddrList) 1021 } else { 1022 err = suite.stateDB.DeleteContractMethodBlockedList(tc.targetAddrList) 1023 } 1024 if tc.success { 1025 suite.Require().NoError(err) 1026 } else { 1027 suite.Require().Error(err) 1028 } 1029 1030 blockedList := suite.stateDB.GetContractMethodBlockedList() 1031 suite.Require().Equal(tc.expectedLen, len(blockedList)) 1032 if tc.expectedLen != 0 { 1033 ok := types.BlockedContractListIsEqual(suite.T(), tc.expectedContractList, blockedList) 1034 suite.Require().True(ok) 1035 } 1036 }) 1037 } 1038 } 1039 1040 func (suite *StateDBTestSuite) TestCommitStateDB_ContractMethodBlockedList_BlockedList() { 1041 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 1042 bcMethodOne1 := types.BlockedContract{ 1043 Address: ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 1044 BlockMethods: types.ContractMethods{ 1045 types.ContractMethod{ 1046 Sign: "aaaa", 1047 Extra: "aaaa()", 1048 }, 1049 }, 1050 } 1051 bcMethodTwo1 := types.BlockedContract{ 1052 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 1053 BlockMethods: types.ContractMethods{ 1054 types.ContractMethod{ 1055 Sign: "aaaa", 1056 Extra: "aaaa()", 1057 }, 1058 }, 1059 } 1060 1061 // set contract method blocked list with same blocked list 1062 suite.stateDB.SetContractBlockedList(types.AddressList{addr1}) 1063 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodOne1}) 1064 bcl := suite.stateDB.GetContractMethodBlockedList() 1065 ok := types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{bcMethodOne1}, bcl) 1066 suite.Require().True(ok) 1067 // set contract method blocked list with not same blocked list 1068 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodTwo1}) 1069 bcl = suite.stateDB.GetContractMethodBlockedList() 1070 ok = types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{bcMethodOne1, bcMethodTwo1}, bcl) 1071 suite.Require().True(ok) 1072 1073 // set blocked list with same method blocked list 1074 suite.stateDB.SetContractBlockedList(types.AddressList{addr1}) 1075 bcl = suite.stateDB.GetContractMethodBlockedList() 1076 expect := types.NewBlockContract(bcMethodOne1.Address, nil) 1077 ok = types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{*expect, bcMethodTwo1}, bcl) 1078 suite.Require().True(ok) 1079 1080 } 1081 1082 func (suite *StateDBTestSuite) TestCommitStateDB_GetContractMethodBlockedByAddress() { 1083 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 1084 addr2 := ethcmn.BytesToAddress([]byte{0x1}).Bytes() 1085 bcMethodOne1 := types.BlockedContract{ 1086 Address: ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 1087 BlockMethods: types.ContractMethods{ 1088 types.ContractMethod{ 1089 Sign: "aaaa", 1090 Extra: "aaaa()", 1091 }, 1092 }, 1093 } 1094 bcMethodTwo1 := types.BlockedContract{ 1095 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 1096 BlockMethods: types.ContractMethods{ 1097 types.ContractMethod{ 1098 Sign: "bbbb", 1099 Extra: "bbbb()", 1100 }, 1101 }, 1102 } 1103 1104 // get blocked list is not exist 1105 bc := suite.stateDB.GetContractMethodBlockedByAddress(addr1) 1106 suite.Require().Nil(bc) 1107 1108 // get blocked list 1109 suite.stateDB.SetContractBlockedList(types.AddressList{addr1, addr2}) 1110 bc = suite.stateDB.GetContractMethodBlockedByAddress(addr1) 1111 suite.Require().NotNil(bc) 1112 suite.Require().Equal(0, len(bc.BlockMethods)) 1113 suite.Require().Equal(addr1, bc.Address.Bytes()) 1114 1115 // get blocked list 1116 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodOne1}) 1117 bc = suite.stateDB.GetContractMethodBlockedByAddress(addr1) 1118 suite.Require().NotNil(bc) 1119 ok := types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{bcMethodOne1}, types.BlockedContractList{*bc}) 1120 suite.Require().True(ok) 1121 1122 // get blocked list from cache 1123 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodTwo1}) 1124 bc = suite.stateDB.GetContractMethodBlockedByAddress(addr2) 1125 suite.Require().NotNil(bc) 1126 ok = types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{bcMethodTwo1}, types.BlockedContractList{*bc}) 1127 suite.Require().True(ok) 1128 1129 bc = suite.stateDB.GetContractMethodBlockedByAddress(addr2) 1130 suite.Require().NotNil(bc) 1131 ok = types.BlockedContractListIsEqual(suite.T(), types.BlockedContractList{bcMethodTwo1}, types.BlockedContractList{*bc}) 1132 suite.Require().True(ok) 1133 } 1134 func (suite *StateDBTestSuite) TestCacheSet() { 1135 addr := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 1136 method1 := types.ContractMethod{ 1137 Sign: "aaaa", 1138 Extra: "aaaa()", 1139 } 1140 method2 := types.ContractMethod{ 1141 Sign: "bbbb", 1142 Extra: "bbbb()", 1143 } 1144 sourceBc := types.BlockedContract{ 1145 Address: addr, 1146 BlockMethods: types.ContractMethods{ 1147 method1, method2, 1148 }, 1149 } 1150 sourceBcl := types.BlockedContractList{sourceBc} 1151 suite.stateDB.InsertContractMethodBlockedList(sourceBcl) 1152 bc := suite.stateDB.GetContractMethodBlockedByAddress(addr) 1153 methods := &bc.BlockMethods 1154 *methods = (*methods)[0:0] 1155 *methods = append(*methods, types.ContractMethod{ 1156 Sign: "dddd", 1157 Extra: "dddd()", 1158 }) 1159 bc = suite.stateDB.GetContractMethodBlockedByAddress(addr) 1160 ok := types.BlockedContractListIsEqual(suite.T(), sourceBcl, types.BlockedContractList{*bc}) 1161 suite.Require().True(ok) 1162 } 1163 func (suite *StateDBTestSuite) TestCommitStateDB_IsContractMethodBlocked() { 1164 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 1165 addr2 := ethcmn.BytesToAddress([]byte{0x1}).Bytes() 1166 bcMethodOne1 := types.BlockedContract{ 1167 Address: ethcmn.BytesToAddress([]byte{0x0}).Bytes(), 1168 BlockMethods: types.ContractMethods{ 1169 types.ContractMethod{ 1170 Sign: "aaaa", 1171 Extra: "aaaa()", 1172 }, 1173 }, 1174 } 1175 bcMethodTwo1 := types.BlockedContract{ 1176 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 1177 BlockMethods: types.ContractMethods{ 1178 types.ContractMethod{ 1179 Sign: "bbbb", 1180 Extra: "bbbb()", 1181 }, 1182 }, 1183 } 1184 1185 // contract method is not exist 1186 ok := suite.stateDB.IsContractMethodBlocked(addr1, "") 1187 suite.Require().False(ok) 1188 ok = suite.stateDB.IsContractMethodBlocked(addr1, "aaaa") 1189 suite.Require().False(ok) 1190 1191 // contract all method is blocked 1192 suite.stateDB.SetContractBlockedList(types.AddressList{addr1, addr2}) 1193 ok = suite.stateDB.IsContractMethodBlocked(addr1, "") 1194 suite.Require().False(ok) 1195 ok = suite.stateDB.IsContractMethodBlocked(addr1, "aaaa") 1196 suite.Require().False(ok) 1197 1198 // contract aaaa method is blocked 1199 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodOne1}) 1200 ok = suite.stateDB.IsContractMethodBlocked(addr1, "") 1201 suite.Require().False(ok) 1202 ok = suite.stateDB.IsContractMethodBlocked(addr1, "aaaa") 1203 suite.Require().True(ok) 1204 1205 // contract aaaa method is blocked 1206 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodTwo1}) 1207 ok = suite.stateDB.IsContractMethodBlocked(addr1, "") 1208 suite.Require().False(ok) 1209 ok = suite.stateDB.IsContractMethodBlocked(addr1, "bbbb") 1210 suite.Require().False(ok) 1211 } 1212 1213 func (suite *StateDBTestSuite) TestCommitStateDB_IsContractInBlockedList() { 1214 addr1 := ethcmn.BytesToAddress([]byte{0x0}).Bytes() 1215 addr2 := ethcmn.BytesToAddress([]byte{0x1}).Bytes() 1216 1217 bcMethodTwo1 := types.BlockedContract{ 1218 Address: ethcmn.BytesToAddress([]byte{0x1}).Bytes(), 1219 BlockMethods: types.ContractMethods{ 1220 types.ContractMethod{ 1221 Sign: "bbbb", 1222 Extra: "bbbb()", 1223 }, 1224 }, 1225 } 1226 // contract is not exist 1227 ok := suite.stateDB.IsContractInBlockedList(addr1) 1228 suite.Require().False(ok) 1229 ok = suite.stateDB.IsContractInBlockedList(addr2) 1230 suite.Require().False(ok) 1231 // contract is exist 1232 suite.stateDB.SetContractBlockedList(types.AddressList{addr1}) 1233 ok = suite.stateDB.IsContractInBlockedList(addr1) 1234 suite.Require().True(ok) 1235 ok = suite.stateDB.IsContractInBlockedList(addr2) 1236 suite.Require().False(ok) 1237 1238 // contract method is blocked 1239 suite.stateDB.InsertContractMethodBlockedList(types.BlockedContractList{bcMethodTwo1}) 1240 ok = suite.stateDB.IsContractInBlockedList(addr2) 1241 suite.Require().False(ok) 1242 ok = suite.stateDB.IsContractInBlockedList(addr1) 1243 suite.Require().True(ok) 1244 } 1245 1246 func (suite *StateDBTestSuite) TestResetCommitStateDB() { 1247 params := suite.app.EvmKeeper.GenerateCSDBParams() 1248 csdb := types.CreateEmptyCommitStateDB(params, suite.ctx) 1249 types.ResetCommitStateDB(csdb, params, &suite.ctx) 1250 expect := types.CreateEmptyCommitStateDB(params, suite.ctx) 1251 suite.Require().Equal(expect, csdb) 1252 }