2022-01-05 07:28:27 +00:00
|
|
|
package statedb_test
|
|
|
|
|
|
|
|
import (
|
2022-01-06 17:10:51 +00:00
|
|
|
"bytes"
|
|
|
|
"errors"
|
2022-01-05 07:28:27 +00:00
|
|
|
"math/big"
|
|
|
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2022-01-06 17:10:51 +00:00
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2022-06-19 09:43:41 +00:00
|
|
|
"github.com/evmos/ethermint/x/evm/statedb"
|
2022-01-05 07:28:27 +00:00
|
|
|
)
|
|
|
|
|
2022-01-06 17:10:51 +00:00
|
|
|
var (
|
|
|
|
_ statedb.Keeper = &MockKeeper{}
|
|
|
|
errAddress common.Address = common.BigToAddress(big.NewInt(100))
|
|
|
|
emptyCodeHash = crypto.Keccak256(nil)
|
|
|
|
)
|
2022-01-05 07:28:27 +00:00
|
|
|
|
2022-01-06 17:10:51 +00:00
|
|
|
type MockAcount struct {
|
|
|
|
account statedb.Account
|
|
|
|
states statedb.Storage
|
|
|
|
}
|
2022-01-05 07:28:27 +00:00
|
|
|
|
2022-01-06 17:10:51 +00:00
|
|
|
type MockKeeper struct {
|
|
|
|
accounts map[common.Address]MockAcount
|
2022-01-05 07:28:27 +00:00
|
|
|
codes map[common.Hash][]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewMockKeeper() *MockKeeper {
|
|
|
|
return &MockKeeper{
|
2022-01-06 17:10:51 +00:00
|
|
|
accounts: make(map[common.Address]MockAcount),
|
2022-01-05 07:28:27 +00:00
|
|
|
codes: make(map[common.Hash][]byte),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-05 18:18:02 +00:00
|
|
|
func (k MockKeeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account {
|
2022-01-05 07:28:27 +00:00
|
|
|
acct, ok := k.accounts[addr]
|
|
|
|
if !ok {
|
2022-01-05 18:18:02 +00:00
|
|
|
return nil
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
2022-01-06 17:10:51 +00:00
|
|
|
return &acct.account
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash {
|
2022-01-06 17:10:51 +00:00
|
|
|
return k.accounts[addr].states[key]
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) GetCode(ctx sdk.Context, codeHash common.Hash) []byte {
|
|
|
|
return k.codes[codeHash]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) {
|
2022-01-06 17:10:51 +00:00
|
|
|
if acct, ok := k.accounts[addr]; ok {
|
|
|
|
for k, v := range acct.states {
|
|
|
|
if !cb(k, v) {
|
|
|
|
return
|
|
|
|
}
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error {
|
2022-01-06 17:10:51 +00:00
|
|
|
if addr == errAddress {
|
|
|
|
return errors.New("mock db error")
|
|
|
|
}
|
|
|
|
acct, exists := k.accounts[addr]
|
|
|
|
if exists {
|
|
|
|
// update
|
|
|
|
acct.account = account
|
|
|
|
k.accounts[addr] = acct
|
|
|
|
} else {
|
|
|
|
k.accounts[addr] = MockAcount{account: account, states: make(statedb.Storage)}
|
|
|
|
}
|
2022-01-05 07:28:27 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) {
|
2022-01-06 17:10:51 +00:00
|
|
|
if acct, ok := k.accounts[addr]; ok {
|
|
|
|
if len(value) == 0 {
|
|
|
|
delete(acct.states, key)
|
|
|
|
} else {
|
|
|
|
acct.states[key] = common.BytesToHash(value)
|
|
|
|
}
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) SetCode(ctx sdk.Context, codeHash []byte, code []byte) {
|
|
|
|
k.codes[common.BytesToHash(codeHash)] = code
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k MockKeeper) DeleteAccount(ctx sdk.Context, addr common.Address) error {
|
2022-01-06 17:10:51 +00:00
|
|
|
if addr == errAddress {
|
|
|
|
return errors.New("mock db error")
|
|
|
|
}
|
2022-01-05 07:28:27 +00:00
|
|
|
old := k.accounts[addr]
|
|
|
|
delete(k.accounts, addr)
|
2022-01-06 17:10:51 +00:00
|
|
|
if !bytes.Equal(old.account.CodeHash, emptyCodeHash) {
|
|
|
|
delete(k.codes, common.BytesToHash(old.account.CodeHash))
|
2022-01-05 07:28:27 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-01-06 17:10:51 +00:00
|
|
|
|
|
|
|
func (k MockKeeper) Clone() *MockKeeper {
|
|
|
|
accounts := make(map[common.Address]MockAcount, len(k.accounts))
|
|
|
|
for k, v := range k.accounts {
|
|
|
|
accounts[k] = v
|
|
|
|
}
|
|
|
|
codes := make(map[common.Hash][]byte, len(k.codes))
|
|
|
|
for k, v := range k.codes {
|
|
|
|
codes[k] = v
|
|
|
|
}
|
|
|
|
return &MockKeeper{accounts, codes}
|
|
|
|
}
|