From 7eda4721ce8eca11d5c2884a2e02acc2d819336f Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Wed, 3 Jan 2024 23:58:48 +0700 Subject: [PATCH 01/16] remove EthAccount type --- proto/ethermint/types/v1/account.proto | 25 -- types/account.go | 82 ------ types/account.pb.go | 377 ------------------------- types/account_test.go | 58 ---- 4 files changed, 542 deletions(-) delete mode 100644 proto/ethermint/types/v1/account.proto delete mode 100644 types/account.go delete mode 100644 types/account.pb.go delete mode 100644 types/account_test.go diff --git a/proto/ethermint/types/v1/account.proto b/proto/ethermint/types/v1/account.proto deleted file mode 100644 index 1c2a7436ed..0000000000 --- a/proto/ethermint/types/v1/account.proto +++ /dev/null @@ -1,25 +0,0 @@ -syntax = "proto3"; -package ethermint.types.v1; - -import "cosmos/auth/v1beta1/auth.proto"; -import "cosmos_proto/cosmos.proto"; -import "gogoproto/gogo.proto"; - -option go_package = "github.com/EscanBE/evermint/v12/types"; - -// EthAccount implements the authtypes.AccountI interface and embeds an -// authtypes.BaseAccount type. It is compatible with the auth AccountKeeper. -message EthAccount { - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - option (gogoproto.equal) = false; - - option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI"; - - // base_account is an authtypes.BaseAccount - cosmos.auth.v1beta1.BaseAccount base_account = 1 - [(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""]; - - // code_hash is the hash calculated from the code contents - string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""]; -} diff --git a/types/account.go b/types/account.go deleted file mode 100644 index e0719f8f99..0000000000 --- a/types/account.go +++ /dev/null @@ -1,82 +0,0 @@ -package types - -import ( - "bytes" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -var ( - _ authtypes.AccountI = (*EthAccount)(nil) - _ EthAccountI = (*EthAccount)(nil) - _ authtypes.GenesisAccount = (*EthAccount)(nil) - _ codectypes.UnpackInterfacesMessage = (*EthAccount)(nil) -) - -var emptyCodeHash = crypto.Keccak256(nil) - -const ( - // AccountTypeEOA defines the type for externally owned accounts (EOAs) - AccountTypeEOA = int8(iota + 1) - // AccountTypeContract defines the type for contract accounts - AccountTypeContract -) - -// EthAccountI represents the interface of an EVM compatible account -type EthAccountI interface { - authtypes.AccountI - // EthAddress returns the ethereum Address representation of the AccAddress - EthAddress() common.Address - // GetCodeHash returns code hash is the keccak256 hash of the contract code (if any) - GetCodeHash() common.Hash - // SetCodeHash sets the code hash to the account fields - SetCodeHash(code common.Hash) error - // Type returns the type of Ethereum Account (EOA or Contract) - Type() int8 -} - -// ---------------------------------------------------------------------------- -// Main account type -// ---------------------------------------------------------------------------- - -// ProtoAccount defines the prototype function for BaseAccount used for an -// AccountKeeper. -func ProtoAccount() authtypes.AccountI { - return &EthAccount{ - BaseAccount: &authtypes.BaseAccount{}, - CodeHash: common.BytesToHash(emptyCodeHash).String(), - } -} - -// GetBaseAccount returns base account. -func (acc EthAccount) GetBaseAccount() *authtypes.BaseAccount { - return acc.BaseAccount -} - -// EthAddress returns the account address ethereum format. -func (acc EthAccount) EthAddress() common.Address { - return common.BytesToAddress(acc.GetAddress().Bytes()) -} - -// GetCodeHash returns the account code hash in byte format -func (acc EthAccount) GetCodeHash() common.Hash { - return common.HexToHash(acc.CodeHash) -} - -// SetCodeHash sets the account code hash to the EthAccount fields -func (acc *EthAccount) SetCodeHash(codeHash common.Hash) error { - acc.CodeHash = codeHash.Hex() - return nil -} - -// Type returns the type of Ethereum Account (EOA or Contract) -func (acc EthAccount) Type() int8 { - if bytes.Equal(emptyCodeHash, common.HexToHash(acc.CodeHash).Bytes()) { - return AccountTypeEOA - } - return AccountTypeContract -} diff --git a/types/account.pb.go b/types/account.pb.go deleted file mode 100644 index 2b2f567949..0000000000 --- a/types/account.pb.go +++ /dev/null @@ -1,377 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ethermint/types/v1/account.proto - -package types - -import ( - fmt "fmt" - _ "github.com/cosmos/cosmos-proto" - types "github.com/cosmos/cosmos-sdk/x/auth/types" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// EthAccount implements the authtypes.AccountI interface and embeds an -// authtypes.BaseAccount type. It is compatible with the auth AccountKeeper. -type EthAccount struct { - // base_account is an authtypes.BaseAccount - *types.BaseAccount `protobuf:"bytes,1,opt,name=base_account,json=baseAccount,proto3,embedded=base_account" json:"base_account,omitempty" yaml:"base_account"` - // code_hash is the hash calculated from the code contents - CodeHash string `protobuf:"bytes,2,opt,name=code_hash,json=codeHash,proto3" json:"code_hash,omitempty" yaml:"code_hash"` -} - -func (m *EthAccount) Reset() { *m = EthAccount{} } -func (*EthAccount) ProtoMessage() {} -func (*EthAccount) Descriptor() ([]byte, []int) { - return fileDescriptor_4edc057d42a619ef, []int{0} -} -func (m *EthAccount) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *EthAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_EthAccount.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *EthAccount) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthAccount.Merge(m, src) -} -func (m *EthAccount) XXX_Size() int { - return m.Size() -} -func (m *EthAccount) XXX_DiscardUnknown() { - xxx_messageInfo_EthAccount.DiscardUnknown(m) -} - -var xxx_messageInfo_EthAccount proto.InternalMessageInfo - -func init() { - proto.RegisterType((*EthAccount)(nil), "ethermint.types.v1.EthAccount") -} - -func init() { proto.RegisterFile("ethermint/types/v1/account.proto", fileDescriptor_4edc057d42a619ef) } - -var fileDescriptor_4edc057d42a619ef = []byte{ - // 322 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x51, 0xbf, 0x4e, 0x3a, 0x31, - 0x1c, 0x6f, 0x7f, 0xc3, 0x2f, 0x72, 0x38, 0x98, 0x93, 0x01, 0x31, 0x69, 0x2f, 0x97, 0x98, 0xb0, - 0xd0, 0xa6, 0xb8, 0xb1, 0x18, 0x9b, 0x90, 0xe8, 0xca, 0xe8, 0x82, 0xbd, 0xd2, 0x50, 0xa2, 0x47, - 0x09, 0x2d, 0x17, 0x79, 0x03, 0x47, 0x47, 0x47, 0x1e, 0xc2, 0x87, 0x30, 0x4e, 0x8c, 0x4e, 0xc4, - 0x40, 0x4c, 0x9c, 0x79, 0x02, 0xc3, 0xb5, 0x41, 0xa6, 0x7e, 0xff, 0x7c, 0xfe, 0xb4, 0x9f, 0x46, - 0x89, 0x72, 0x5a, 0x4d, 0xf3, 0xd1, 0xd8, 0x51, 0x37, 0x9f, 0x28, 0x4b, 0x0b, 0x46, 0x85, 0x94, - 0x66, 0x36, 0x76, 0x64, 0x32, 0x35, 0xce, 0xc4, 0xf1, 0x1e, 0x41, 0x4a, 0x04, 0x29, 0x58, 0x03, - 0x49, 0x63, 0x73, 0x63, 0xa9, 0x98, 0x39, 0x4d, 0x0b, 0x96, 0x29, 0x27, 0x58, 0xd9, 0x78, 0x4e, - 0xe3, 0xcc, 0xef, 0xfb, 0x65, 0x47, 0x7d, 0x13, 0x56, 0xb5, 0xa1, 0x19, 0x1a, 0x3f, 0xdf, 0x55, - 0x7e, 0x9a, 0x7e, 0xc3, 0x28, 0xea, 0x3a, 0x7d, 0xed, 0x9d, 0xe3, 0xfb, 0xe8, 0x38, 0x13, 0x56, - 0xf5, 0xc3, 0x4d, 0xea, 0x30, 0x81, 0xcd, 0x6a, 0x3b, 0x21, 0x41, 0xa9, 0x74, 0x0a, 0xb6, 0x84, - 0x0b, 0xab, 0x02, 0x8f, 0x9f, 0x2f, 0x57, 0x18, 0x6e, 0x57, 0xf8, 0x74, 0x2e, 0xf2, 0xc7, 0x4e, - 0x7a, 0xa8, 0x91, 0xf6, 0xaa, 0xd9, 0x1f, 0x32, 0x66, 0x51, 0x45, 0x9a, 0x81, 0xea, 0x6b, 0x61, - 0x75, 0xfd, 0x5f, 0x02, 0x9b, 0x15, 0x5e, 0xdb, 0xae, 0xf0, 0x89, 0x27, 0xee, 0x57, 0x69, 0xef, - 0x68, 0x57, 0xdf, 0x08, 0xab, 0x3b, 0xfc, 0x79, 0x81, 0xc1, 0xeb, 0x02, 0x83, 0x9f, 0x05, 0x06, - 0x1f, 0x6f, 0xad, 0xf6, 0x70, 0xe4, 0xf4, 0x2c, 0x23, 0xd2, 0xe4, 0xe1, 0x89, 0xe1, 0x68, 0xd9, - 0xc1, 0x03, 0x7d, 0xf2, 0xe1, 0xf8, 0xc8, 0x82, 0xeb, 0x2d, 0xbf, 0x7a, 0x5f, 0x23, 0xb8, 0x5c, - 0x23, 0xf8, 0xb5, 0x46, 0xf0, 0x65, 0x83, 0xc0, 0x72, 0x83, 0xc0, 0xe7, 0x06, 0x81, 0xbb, 0x8b, - 0x03, 0xb5, 0xae, 0x95, 0x62, 0xcc, 0xbb, 0x54, 0x15, 0xe1, 0x6b, 0x0a, 0xd6, 0xf6, 0x4a, 0xd9, - 0xff, 0x32, 0xaf, 0xcb, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6f, 0xff, 0xc5, 0x26, 0xb8, 0x01, - 0x00, 0x00, -} - -func (m *EthAccount) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *EthAccount) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *EthAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.CodeHash) > 0 { - i -= len(m.CodeHash) - copy(dAtA[i:], m.CodeHash) - i = encodeVarintAccount(dAtA, i, uint64(len(m.CodeHash))) - i-- - dAtA[i] = 0x12 - } - if m.BaseAccount != nil { - { - size, err := m.BaseAccount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintAccount(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintAccount(dAtA []byte, offset int, v uint64) int { - offset -= sovAccount(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *EthAccount) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.BaseAccount != nil { - l = m.BaseAccount.Size() - n += 1 + l + sovAccount(uint64(l)) - } - l = len(m.CodeHash) - if l > 0 { - n += 1 + l + sovAccount(uint64(l)) - } - return n -} - -func sovAccount(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozAccount(x uint64) (n int) { - return sovAccount(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *EthAccount) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAccount - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: EthAccount: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: EthAccount: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BaseAccount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAccount - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthAccount - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthAccount - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.BaseAccount == nil { - m.BaseAccount = &types.BaseAccount{} - } - if err := m.BaseAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CodeHash", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAccount - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthAccount - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthAccount - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CodeHash = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipAccount(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthAccount - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipAccount(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowAccount - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowAccount - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowAccount - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthAccount - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupAccount - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthAccount - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthAccount = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowAccount = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupAccount = fmt.Errorf("proto: unexpected end of group") -) diff --git a/types/account_test.go b/types/account_test.go deleted file mode 100644 index 0d5ecc56dd..0000000000 --- a/types/account_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/suite" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - - cryptocodec "github.com/EscanBE/evermint/v12/crypto/codec" - "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" - encodingcodec "github.com/EscanBE/evermint/v12/encoding/codec" - "github.com/EscanBE/evermint/v12/types" -) - -func init() { - amino := codec.NewLegacyAmino() - cryptocodec.RegisterCrypto(amino) -} - -type AccountTestSuite struct { - suite.Suite - - account *types.EthAccount - cdc codec.JSONCodec -} - -func (suite *AccountTestSuite) SetupTest() { - privKey, err := ethsecp256k1.GenerateKey() - suite.Require().NoError(err) - pubKey := privKey.PubKey() - addr := sdk.AccAddress(pubKey.Address()) - baseAcc := authtypes.NewBaseAccount(addr, pubKey, 10, 50) - suite.account = &types.EthAccount{ - BaseAccount: baseAcc, - CodeHash: common.Hash{}.String(), - } - - interfaceRegistry := codectypes.NewInterfaceRegistry() - encodingcodec.RegisterInterfaces(interfaceRegistry) - suite.cdc = codec.NewProtoCodec(interfaceRegistry) -} - -func TestAccountTestSuite(t *testing.T) { - suite.Run(t, new(AccountTestSuite)) -} - -func (suite *AccountTestSuite) TestAccountType() { - suite.account.CodeHash = common.BytesToHash(crypto.Keccak256(nil)).Hex() - suite.Require().Equal(types.AccountTypeEOA, suite.account.Type()) - suite.account.CodeHash = common.BytesToHash(crypto.Keccak256([]byte{1, 2, 3})).Hex() - suite.Require().Equal(types.AccountTypeContract, suite.account.Type()) -} From a887157338739375414eaddc9db608177ca80ea8 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 00:32:38 +0700 Subject: [PATCH 02/16] define new store key for storing code hash --- x/evm/types/key.go | 19 +++++-- x/evm/types/key_test.go | 107 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 x/evm/types/key_test.go diff --git a/x/evm/types/key.go b/x/evm/types/key.go index ec35abbdf1..68dd442222 100644 --- a/x/evm/types/key.go +++ b/x/evm/types/key.go @@ -1,6 +1,7 @@ package types import ( + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" ) @@ -26,6 +27,7 @@ const ( prefixCode = iota + 1 prefixStorage prefixParams + prefixCodeHash ) // prefix bytes for the EVM transient store @@ -38,9 +40,10 @@ const ( // KVStore key prefixes var ( - KeyPrefixCode = []byte{prefixCode} - KeyPrefixStorage = []byte{prefixStorage} - KeyPrefixParams = []byte{prefixParams} + KeyPrefixCode = []byte{prefixCode} + KeyPrefixStorage = []byte{prefixStorage} + KeyPrefixParams = []byte{prefixParams} + KeyPrefixCodeHash = []byte{prefixCodeHash} ) // Transient Store key prefixes @@ -60,3 +63,13 @@ func AddressStoragePrefix(address common.Address) []byte { func StateKey(address common.Address, key []byte) []byte { return append(AddressStoragePrefix(address), key...) } + +// AddressCodeHashKey defines the full key under which an account code hash is stored. +func AddressCodeHashKey(address common.Address, accountNumber uint64) []byte { + bz := append(KeyPrefixCodeHash, address.Bytes()...) + bzAccountNumber := sdk.Uint64ToBigEndian(accountNumber) + if len(bzAccountNumber) < 8 { + bzAccountNumber = append(make([]byte, 8-len(bzAccountNumber)), bzAccountNumber...) + } + return append(bz, bzAccountNumber...) +} diff --git a/x/evm/types/key_test.go b/x/evm/types/key_test.go new file mode 100644 index 0000000000..7d75d52425 --- /dev/null +++ b/x/evm/types/key_test.go @@ -0,0 +1,107 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + "reflect" + "testing" +) + +func TestAddressCodeHashKey(t *testing.T) { + tests := []struct { + name string + address common.Address + accountNumber uint64 + want []byte + }{ + { + name: "normal", + address: common.BytesToAddress([]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + }), + accountNumber: sdk.BigEndianToUint64([]byte{ + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + }), + want: []byte{ + KeyPrefixCodeHash[0], + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + }, + }, + { + name: "account number is 8 bytes key length", + address: common.BytesToAddress([]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + }), + accountNumber: sdk.BigEndianToUint64([]byte{ + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + }), + want: []byte{ + KeyPrefixCodeHash[0], + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 8 bytes of account number, no prefix + }, + }, + { + name: "account number is 7 bytes length", + address: common.BytesToAddress([]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + }), + accountNumber: sdk.BigEndianToUint64([]byte{ + 0x00, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + }), + want: []byte{ + KeyPrefixCodeHash[0], + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + 0x00, // 1 bytes prefix of account number + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // 7 bytes account number + }, + }, + { + name: "account number is 6 bytes length", + address: common.BytesToAddress([]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + }), + accountNumber: sdk.BigEndianToUint64([]byte{ + 0x00, 0x00, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + }), + want: []byte{ + KeyPrefixCodeHash[0], + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + 0x00, 0x00, // 2 bytes prefix of account number + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, // 6 bytes account number + }, + }, + { + name: "account number is 0 bytes length", + address: common.BytesToAddress([]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + }), + accountNumber: 0, + want: []byte{ + KeyPrefixCodeHash[0], + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 bytes prefix of account number + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := AddressCodeHashKey(tt.address, tt.accountNumber); !reflect.DeepEqual(got, tt.want) { + t.Errorf("AddressCodeHashPrefix() = %v, want %v", got, tt.want) + } + }) + } +} From d9bbe8e87e16269560903bf5e41f33b047cf16f3 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 00:33:47 +0700 Subject: [PATCH 03/16] remove registration of concrete interface --- types/codec.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/types/codec.go b/types/codec.go index 287716340e..d492304d79 100644 --- a/types/codec.go +++ b/types/codec.go @@ -3,20 +3,11 @@ package types import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/tx" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // RegisterInterfaces registers the tendermint concrete client-related // implementations and interfaces. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterImplementations( - (*authtypes.AccountI)(nil), - &EthAccount{}, - ) - registry.RegisterImplementations( - (*authtypes.GenesisAccount)(nil), - &EthAccount{}, - ) registry.RegisterImplementations( (*tx.TxExtensionOptionI)(nil), &ExtensionOptionsWeb3Tx{}, From e1fd950f0f3340b04ec7aa5f25f6f9bf7503f63c Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 01:38:48 +0700 Subject: [PATCH 04/16] introduce new type CodeHash for typed code & convenient method --- x/evm/types/code_hash.go | 22 ++++++++++ x/evm/types/code_hash_test.go | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 x/evm/types/code_hash.go create mode 100644 x/evm/types/code_hash_test.go diff --git a/x/evm/types/code_hash.go b/x/evm/types/code_hash.go new file mode 100644 index 0000000000..966971a431 --- /dev/null +++ b/x/evm/types/code_hash.go @@ -0,0 +1,22 @@ +package types + +import ( + "bytes" +) + +// CodeHash represents the keccak256 hash of the code of a contract. +type CodeHash []byte + +// IsEmptyCodeHash returns true if the code hash is empty or equals to keccak256 of nil. +func (ch CodeHash) IsEmptyCodeHash() bool { + return len(ch) == 0 || bytes.Equal(ch, EmptyCodeHash) +} + +// Bytes returns the byte representation of the code hash. +// Returns empty if the code hash is nil. +func (ch CodeHash) Bytes() []byte { + if ch == nil { + return []byte{} + } + return ch +} diff --git a/x/evm/types/code_hash_test.go b/x/evm/types/code_hash_test.go new file mode 100644 index 0000000000..5016db6fbb --- /dev/null +++ b/x/evm/types/code_hash_test.go @@ -0,0 +1,75 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/crypto" + "reflect" + "testing" +) + +func TestCodeHash_IsEmptyCodeHash(t *testing.T) { + tests := []struct { + name string + ch CodeHash + want bool + }{ + { + name: "nil code hash", + ch: nil, + want: true, + }, + { + name: "empty code hash", + ch: []byte{}, + want: true, + }, + { + name: "non-empty code hash", + ch: crypto.Keccak256([]byte("pseudo")), + want: false, + }, + { + name: "equals to keccak256 of nil", + ch: EmptyCodeHash, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.ch.IsEmptyCodeHash(); got != tt.want { + t.Errorf("IsEmptyCodeHash() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCodeHash_Bytes(t *testing.T) { + randomCodeHash := crypto.Keccak256([]byte("pseudo")) + tests := []struct { + name string + ch CodeHash + want []byte + }{ + { + name: "normal", + ch: CodeHash(randomCodeHash), + want: randomCodeHash, + }, + { + name: "normal empty code hash", + ch: CodeHash(EmptyCodeHash), + want: []byte(EmptyCodeHash), + }, + { + name: "nil returns empty", + ch: CodeHash(nil), + want: []byte{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.ch.Bytes(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Bytes() = %v, want %v", got, tt.want) + } + }) + } +} From c09c919683cb66fef1822cf20696fafdd21d931b Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 01:39:36 +0700 Subject: [PATCH 05/16] expand x/evm keeper with new methods to work with code hash & account type checking --- x/evm/keeper/eth_account.go | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 x/evm/keeper/eth_account.go diff --git a/x/evm/keeper/eth_account.go b/x/evm/keeper/eth_account.go new file mode 100644 index 0000000000..f299889902 --- /dev/null +++ b/x/evm/keeper/eth_account.go @@ -0,0 +1,66 @@ +package keeper + +import ( + "fmt" + evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/ethereum/go-ethereum/common" +) + +// IsContractAccount returns true if the given address is a contract account. +// If the code hash is not found, account is not contract. +func (k *Keeper) IsContractAccount(ctx sdk.Context, addr common.Address) bool { + account := k.accountKeeper.GetAccount(ctx, addr.Bytes()) + if account == nil { + return false + } + + return k.IsAccountIContractAccount(ctx, account) +} + +// IsAccountIContractAccount returns true if the given AccountI is a contract account. +// If len of address is not 20 or the code hash is not found, account is not contract. +func (k *Keeper) IsAccountIContractAccount(ctx sdk.Context, account authtypes.AccountI) bool { + bzAddress := account.GetAddress().Bytes() + if len(bzAddress) != 20 { // Ethereum contract address is always 20 bytes + return false + } + + store := ctx.KVStore(k.storeKey) + return store.Has(evmtypes.AddressCodeHashKey(common.BytesToAddress(bzAddress), account.GetAccountNumber())) +} + +// GetAccountICodeHash returns the code hash of the given AccountI. +// If code hash is not found, keccak256(nil) will be returned. +func (k *Keeper) GetAccountICodeHash(ctx sdk.Context, account authtypes.AccountI) evmtypes.CodeHash { + bzAddress := account.GetAddress().Bytes() + if len(bzAddress) != 20 { // Ethereum contract address is always 20 bytes + return evmtypes.EmptyCodeHash + } + + store := ctx.KVStore(k.storeKey) + codeHash := store.Get(evmtypes.AddressCodeHashKey(common.BytesToAddress(bzAddress), account.GetAccountNumber())) + if len(codeHash) == 0 { + codeHash = evmtypes.EmptyCodeHash + } + return codeHash +} + +// SetAccountICodeHash persists code hash of the given AccountI into the store. +// If code hash is empty, it will be deleted from the store. +func (k *Keeper) SetAccountICodeHash(ctx sdk.Context, account authtypes.AccountI, codeHash evmtypes.CodeHash) { + bzAddress := account.GetAddress().Bytes() + if len(bzAddress) != 20 { // Ethereum contract address is always 20 bytes + panic(fmt.Sprintf("address %s is not a valid contract address", account.GetAddress())) + } + + store := ctx.KVStore(k.storeKey) + + storeKeyForAccount := evmtypes.AddressCodeHashKey(common.BytesToAddress(bzAddress), account.GetAccountNumber()) + if codeHash.IsEmptyCodeHash() { + store.Delete(storeKeyForAccount) + } else { + store.Set(storeKeyForAccount, codeHash) + } +} From cb261c7582add377f61cda24e96d8ed7c35c6815 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 01:40:33 +0700 Subject: [PATCH 06/16] use default proto BaseAccount by x/auth --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index 1bd275e364..e32bde5d7a 100644 --- a/app/app.go +++ b/app/app.go @@ -412,7 +412,7 @@ func NewEvermint( // use custom Ethermint account for contracts chainApp.AccountKeeper = authkeeper.NewAccountKeeper( - appCodec, keys[authtypes.StoreKey], evertypes.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(), authAddr, + appCodec, keys[authtypes.StoreKey], authtypes.ProtoBaseAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(), authAddr, ) chainApp.BankKeeper = bankkeeper.NewBaseKeeper( appCodec, keys[banktypes.StoreKey], chainApp.AccountKeeper, chainApp.BlockedAddrs(), authAddr, From a4124c48b0f91db1b90b5491fbfb3d47f9c07385 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 02:11:24 +0700 Subject: [PATCH 07/16] migrate x/evm genesis account behavior --- x/evm/genesis.go | 64 +++++++++++++++++----------------- x/evm/genesis_test.go | 81 +++++++++++++++++++++++++++++++------------ 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/x/evm/genesis.go b/x/evm/genesis.go index 1a014905ff..76e272330a 100644 --- a/x/evm/genesis.go +++ b/x/evm/genesis.go @@ -1,7 +1,6 @@ package evm import ( - "bytes" "fmt" abci "github.com/cometbft/cometbft/abci/types" @@ -10,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/evm/keeper" "github.com/EscanBE/evermint/v12/x/evm/types" ) @@ -35,36 +33,31 @@ func InitGenesis( } for _, account := range data.Accounts { + code := common.Hex2Bytes(account.Code) + storage := account.Storage + + if len(code) < 1 && len(storage) < 1 { + continue + } + address := common.HexToAddress(account.Address) accAddress := sdk.AccAddress(address.Bytes()) - // check that the EVM balance the matches the account balance + acc := accountKeeper.GetAccount(ctx, accAddress) if acc == nil { panic(fmt.Errorf("account not found for address %s", account.Address)) } - ethAcct, ok := acc.(evertypes.EthAccountI) - if !ok { - panic( - fmt.Errorf("account %s must be an EthAccount interface, got %T", - account.Address, acc, - ), - ) - } - code := common.Hex2Bytes(account.Code) - codeHash := crypto.Keccak256Hash(code) - - // we ignore the empty Code hash checking, see ethermint PR#1234 - if len(account.Code) != 0 && !bytes.Equal(ethAcct.GetCodeHash().Bytes(), codeHash.Bytes()) { - s := "the evm state code doesn't match with the codehash\n" - panic(fmt.Sprintf("%s account: %s , evm state codehash: %v, ethAccount codehash: %v, evm state code: %s\n", - s, account.Address, codeHash, ethAcct.GetCodeHash(), account.Code)) + if len(code) > 0 { + codeHash := crypto.Keccak256Hash(code) + k.SetAccountICodeHash(ctx, acc, codeHash.Bytes()) + k.SetCode(ctx, codeHash.Bytes(), code) } - k.SetCode(ctx, codeHash.Bytes(), code) - - for _, storage := range account.Storage { - k.SetState(ctx, address, common.HexToHash(storage.Key), common.HexToHash(storage.Value).Bytes()) + if len(account.Storage) > 0 { + for _, storage := range account.Storage { + k.SetState(ctx, address, common.HexToHash(storage.Key), common.HexToHash(storage.Value).Bytes()) + } } } @@ -75,19 +68,26 @@ func InitGenesis( func ExportGenesis(ctx sdk.Context, k *keeper.Keeper, ak types.AccountKeeper) *types.GenesisState { var ethGenAccounts []types.GenesisAccount ak.IterateAccounts(ctx, func(account authtypes.AccountI) bool { - ethAccount, ok := account.(evertypes.EthAccountI) - if !ok { - // ignore non EthAccounts + codeHash := k.GetAccountICodeHash(ctx, account) + contractAddr := common.BytesToAddress(account.GetAddress().Bytes()) + storage := k.GetAccountStorage(ctx, contractAddr) + + if codeHash.IsEmptyCodeHash() && len(storage) < 1 { return false } - addr := ethAccount.EthAddress() - - storage := k.GetAccountStorage(ctx, addr) - genAccount := types.GenesisAccount{ - Address: addr.String(), - Code: common.Bytes2Hex(k.GetCode(ctx, ethAccount.GetCodeHash())), + Address: contractAddr.String(), + Code: func(codeHash types.CodeHash) string { + if codeHash.IsEmptyCodeHash() { + return "" + } + code := k.GetCode(ctx, common.BytesToHash(codeHash.Bytes())) + if len(code) < 1 { + return "" + } + return common.Bytes2Hex(code) + }(codeHash), Storage: storage, } diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go index 866e5354f2..4154f11501 100644 --- a/x/evm/genesis_test.go +++ b/x/evm/genesis_test.go @@ -1,12 +1,12 @@ package evm_test import ( + "encoding/hex" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/evm" "github.com/EscanBE/evermint/v12/x/evm/statedb" "github.com/EscanBE/evermint/v12/x/evm/types" @@ -52,7 +52,7 @@ func (suite *EvmTestSuite) TestInitGenesis() { false, }, { - "account not found", + "account without code will be ignored, no matter account exists in auth store or not", func() {}, &types.GenesisState{ Params: types.DefaultParams(), @@ -62,10 +62,10 @@ func (suite *EvmTestSuite) TestInitGenesis() { }, }, }, - true, + false, }, { - "invalid account type", + "accept account type BaseAccount, no code, no storage", func() { acc := authtypes.NewBaseAccountWithAddress(address.Bytes()) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) @@ -78,59 +78,73 @@ func (suite *EvmTestSuite) TestInitGenesis() { }, }, }, - true, + false, }, { - "invalid code hash", + "accept account type BaseAccount, with code and storage", func() { - acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes()) - suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + vmdb.AddBalance(address, big.NewInt(1)) }, &types.GenesisState{ Params: types.DefaultParams(), Accounts: []types.GenesisAccount{ { Address: address.String(), - Code: "ffffffff", + Code: "12345678", + Storage: types.Storage{ + {Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()}, + }, }, }, }, - true, + false, }, { - "ignore empty account code checking", + "accept account type BaseAccount, with only code and no storage", func() { - acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes()) - - suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + vmdb.AddBalance(address, big.NewInt(1)) }, &types.GenesisState{ Params: types.DefaultParams(), Accounts: []types.GenesisAccount{ { Address: address.String(), - Code: "", + Code: "12345678", }, }, }, false, }, { - "ignore empty account code checking with non-empty codehash", + "accept account type BaseAccount, with storage and no code", func() { - ethAcc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(address.Bytes(), nil, 0, 0), - CodeHash: common.BytesToHash([]byte{1, 2, 3}).Hex(), - } + vmdb.AddBalance(address, big.NewInt(1)) + }, + &types.GenesisState{ + Params: types.DefaultParams(), + Accounts: []types.GenesisAccount{ + { + Address: address.String(), + Storage: types.Storage{ + {Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()}, + }, + }, + }, + }, + false, + }, + { + "ignore empty account code & storage checking", + func() { + acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes()) - suite.app.AccountKeeper.SetAccount(suite.ctx, ethAcc) + suite.app.AccountKeeper.SetAccount(suite.ctx, acc) }, &types.GenesisState{ Params: types.DefaultParams(), Accounts: []types.GenesisAccount{ { Address: address.String(), - Code: "", }, }, }, @@ -154,11 +168,32 @@ func (suite *EvmTestSuite) TestInitGenesis() { }, ) } else { + genesisState := tc.genState suite.Require().NotPanics( func() { - _ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *tc.genState) + _ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *genesisState) }, ) + + for _, account := range tc.genState.Accounts { + if len(account.Code) > 0 { + address := common.HexToAddress(account.Address) + acct := suite.app.AccountKeeper.GetAccount(suite.ctx, address.Bytes()) + suite.Require().NotNilf(acct, "account not found: %s", account.Address) + + codeHash := suite.app.EvmKeeper.GetAccountICodeHash(suite.ctx, acct) + suite.Falsef(codeHash.IsEmptyCodeHash(), "code hash of account %s is empty", account.Address) + + suite.Equalf(account.Code, hex.EncodeToString(suite.app.EvmKeeper.GetCode(suite.ctx, common.BytesToHash(codeHash.Bytes()))), "code of account %s is not equal", account.Address) + } + + if len(account.Storage) > 0 { + address := common.HexToAddress(account.Address) + storage := suite.app.EvmKeeper.GetAccountStorage(suite.ctx, address) + + suite.Require().Len(storage, len(account.Storage), "storage of account %s is not equal", account.Address) + } + } } }) } From c54603a70050f0480b9b5e6c5894111da62ef92f Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 02:27:58 +0700 Subject: [PATCH 08/16] genesis account is now base account --- client/testnet.go | 12 ++---------- cmd/evmd/genaccounts.go | 9 +-------- cmd/evmd/testnet.go | 11 ++--------- ibc/testing/chain.go | 8 +------- testutil/network/network.go | 7 +------ 5 files changed, 7 insertions(+), 40 deletions(-) diff --git a/client/testnet.go b/client/testnet.go index 8d67e987c2..1aca2ae75d 100644 --- a/client/testnet.go +++ b/client/testnet.go @@ -15,8 +15,6 @@ import ( "path/filepath" "strings" - "github.com/ethereum/go-ethereum/common" - tmconfig "github.com/cometbft/cometbft/config" tmrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/types" @@ -341,10 +339,7 @@ func initTestnetFiles( } genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins.Sort()}) - genAccounts = append(genAccounts, &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) valTokens := sdk.TokensFromConsensusPower(100, evertypes.PowerReduction) createValMsg, err := stakingtypes.NewMsgCreateValidator( @@ -417,10 +412,7 @@ func initTestnetFiles( sdk.NewCoin(constants.BaseDenom, sdk.TokensFromConsensusPower(1000, evertypes.PowerReduction)), } genBalances = append(genBalances, banktypes.Balance{Address: normalAccountAddr.String(), Coins: coins.Sort()}) - genAccounts = append(genAccounts, &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(normalAccountAddr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(normalAccountAddr, nil, 0, 0)) } if err := initGenFiles(clientCtx, mbm, args.chainID, constants.BaseDenom, genAccounts, genBalances, genFiles, args.numValidators); err != nil { diff --git a/cmd/evmd/genaccounts.go b/cmd/evmd/genaccounts.go index 8bf1cfd6f6..a1a66c226d 100644 --- a/cmd/evmd/genaccounts.go +++ b/cmd/evmd/genaccounts.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" @@ -20,9 +19,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - "github.com/EscanBE/evermint/v12/types" - evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" - appkeyring "github.com/EscanBE/evermint/v12/crypto/keyring" vestingcli "github.com/EscanBE/evermint/v12/x/vesting/client/cli" @@ -202,10 +198,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa ) default: - genAccount = &types.EthAccount{ - BaseAccount: baseAccount, - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - } + genAccount = baseAccount } if err := genAccount.Validate(); err != nil { diff --git a/cmd/evmd/testnet.go b/cmd/evmd/testnet.go index 2fb31cd517..631e8c9773 100644 --- a/cmd/evmd/testnet.go +++ b/cmd/evmd/testnet.go @@ -13,7 +13,6 @@ import ( "github.com/cometbft/cometbft/types" tmtime "github.com/cometbft/cometbft/types/time" clientconfig "github.com/cosmos/cosmos-sdk/client/config" - "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" "github.com/spf13/viper" "net" @@ -334,10 +333,7 @@ func initTestnetFiles( } genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins.Sort()}) - genAccounts = append(genAccounts, &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) valTokens := sdk.TokensFromConsensusPower(100, evertypes.PowerReduction) createValMsg, err := stakingtypes.NewMsgCreateValidator( @@ -412,10 +408,7 @@ func initTestnetFiles( sdk.NewCoin(constants.BaseDenom, sdk.TokensFromConsensusPower(1000, evertypes.PowerReduction)), } genBalances = append(genBalances, banktypes.Balance{Address: normalAccountAddr.String(), Coins: coins.Sort()}) - genAccounts = append(genAccounts, &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(normalAccountAddr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(normalAccountAddr, nil, 0, 0)) } if err := initGenFiles(clientCtx, mbm, args.chainID, constants.BaseDenom, genAccounts, genBalances, genFiles, args.numValidators); err != nil { diff --git a/ibc/testing/chain.go b/ibc/testing/chain.go index a4b44412f3..f3b40bdd71 100644 --- a/ibc/testing/chain.go +++ b/ibc/testing/chain.go @@ -6,8 +6,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ethereum/go-ethereum/common" - sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -21,7 +19,6 @@ import ( "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" evertypes "github.com/EscanBE/evermint/v12/types" - evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" ) // ChainIDPrefix defines the default chain ID prefix for our test chains @@ -59,10 +56,7 @@ func NewTestChain(t *testing.T, coord *ibcgotesting.Coordinator, chainID string) baseAcc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - acc := &evertypes.EthAccount{ - BaseAccount: baseAcc, - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - } + acc := baseAcc amount := sdk.TokensFromConsensusPower(1, evertypes.PowerReduction) diff --git a/testutil/network/network.go b/testutil/network/network.go index 59e9da2f54..311c1dce46 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -25,7 +25,6 @@ import ( tmrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/node" tmclient "github.com/cometbft/cometbft/rpc/client" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" "google.golang.org/grpc" @@ -56,7 +55,6 @@ import ( "github.com/EscanBE/evermint/v12/encoding" "github.com/EscanBE/evermint/v12/server/config" evertypes "github.com/EscanBE/evermint/v12/types" - evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" ) // package-wide network lock to only allow one test network at a time @@ -414,10 +412,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { genFiles = append(genFiles, tmCfg.GenesisFile()) genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()}) - genAccounts = append(genAccounts, &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) commission, err := sdk.NewDecFromStr("0.5") if err != nil { From a6145e4189bf2bef9c276e2b30a6ba6d40abf982 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 02:47:12 +0700 Subject: [PATCH 09/16] update test with new account spec --- x/evm/handler_test.go | 6 +----- x/evm/keeper/setup_test.go | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index eef6a0c992..8133e6a277 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -36,7 +36,6 @@ import ( "github.com/EscanBE/evermint/v12/app" "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/evm" "github.com/EscanBE/evermint/v12/x/evm/statedb" "github.com/EscanBE/evermint/v12/x/evm/types" @@ -148,10 +147,7 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) { queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry()) types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper) - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(address.Bytes(), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) diff --git a/x/evm/keeper/setup_test.go b/x/evm/keeper/setup_test.go index e2ff091de4..6b51211395 100644 --- a/x/evm/keeper/setup_test.go +++ b/x/evm/keeper/setup_test.go @@ -16,7 +16,6 @@ import ( "github.com/EscanBE/evermint/v12/encoding" "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" feemarkettypes "github.com/EscanBE/evermint/v12/x/feemarket/types" abci "github.com/cometbft/cometbft/abci/types" @@ -172,10 +171,7 @@ func (suite *KeeperTestSuite) SetupAppWithT(checkTx bool, t require.TestingT) { evmtypes.RegisterQueryServer(queryHelper, suite.app.EvmKeeper) suite.queryClient = evmtypes.NewQueryClient(queryHelper) - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(suite.address.Bytes(), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) From dcda4698346d4405f6beacb7129bf6e753d6ddcc Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 03:47:31 +0700 Subject: [PATCH 10/16] update statedb to use new code hash implementation --- x/evm/keeper/statedb.go | 23 +++++++++-------------- x/evm/keeper/statedb_test.go | 13 ++++++++++--- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 533d973094..21388e5ef6 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -7,7 +7,6 @@ import ( sdkmath "cosmossdk.io/math" errorsmod "cosmossdk.io/errors" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/evm/statedb" "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/cosmos/cosmos-sdk/store/prefix" @@ -21,7 +20,7 @@ var _ statedb.Keeper = &Keeper{} // StateDB Keeper implementation // ---------------------------------------------------------------------------- -// GetAccount returns nil if account is not exist, returns error if it's not `EthAccountI` +// GetAccount returns nil if account is not exist func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account { acct := k.GetAccountWithoutBalance(ctx, addr) if acct == nil { @@ -115,13 +114,7 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated return err } - codeHash := common.BytesToHash(account.CodeHash) - - if ethAcct, ok := acct.(evertypes.EthAccountI); ok { - if err := ethAcct.SetCodeHash(codeHash); err != nil { - return err - } - } + k.SetAccountICodeHash(ctx, acct, account.CodeHash) k.accountKeeper.SetAccount(ctx, acct) @@ -133,7 +126,7 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated "account updated", "ethereum-address", addr.Hex(), "nonce", account.Nonce, - "codeHash", codeHash.Hex(), + "codeHash", common.BytesToHash(account.CodeHash).Hex(), "balance", account.Balance, ) return nil @@ -186,10 +179,9 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { return nil } - // NOTE: only Ethereum accounts (contracts) can be selfdestructed - _, ok := acct.(evertypes.EthAccountI) - if !ok { - return errorsmod.Wrapf(types.ErrInvalidAccount, "type %T, address %s", acct, addr) + // NOTE: only Ethereum contracts can be self-destructed + if !k.IsAccountIContractAccount(ctx, acct) { + return errorsmod.Wrapf(types.ErrInvalidAccount, "type %T, address %s is not a contract", acct, addr) } // clear balance @@ -197,6 +189,9 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { return err } + // clear code hash + k.SetAccountICodeHash(ctx, acct, types.EmptyCodeHash) + // clear storage k.ForEachStorage(ctx, addr, func(key, _ common.Hash) bool { k.SetState(ctx, addr, key, nil) diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go index 0a7a36a663..2fd47455f4 100644 --- a/x/evm/keeper/statedb_test.go +++ b/x/evm/keeper/statedb_test.go @@ -945,9 +945,9 @@ func (suite *KeeperTestSuite) TestDeleteAccount() { expErr bool }{ { - "remove address", - suite.address, - false, + name: "remove address", + addr: suite.address, + expErr: true, // it is not a contract so an error should be returned }, { "remove unexistent address - returns nil error", @@ -964,6 +964,9 @@ func (suite *KeeperTestSuite) TestDeleteAccount() { for _, tc := range testCases { suite.Run(tc.name, func() { suite.SetupTest() + + acct := suite.app.AccountKeeper.GetAccount(suite.ctx, tc.addr.Bytes()) + err := suite.app.EvmKeeper.DeleteAccount(suite.ctx, tc.addr) if tc.expErr { suite.Require().Error(err) @@ -971,6 +974,10 @@ func (suite *KeeperTestSuite) TestDeleteAccount() { suite.Require().NoError(err) balance := suite.app.EvmKeeper.GetBalance(suite.ctx, tc.addr) suite.Require().Equal(new(big.Int), balance) + + if acct != nil { + suite.True(suite.app.EvmKeeper.GetAccountICodeHash(suite.ctx, acct).IsEmptyCodeHash(), "code hash must be removed") + } } }) } From 7ff95d96f1501fae01701e20718d8dc31efccd10 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 03:49:21 +0700 Subject: [PATCH 11/16] update keeper to use new code hash implementation & account specification --- x/evm/keeper/keeper.go | 8 +------- x/evm/keeper/keeper_test.go | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 9b8ce6217f..3acb21f7ca 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -261,15 +261,9 @@ func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) return nil } - codeHash := types.EmptyCodeHash - ethAcct, ok := acct.(evertypes.EthAccountI) - if ok { - codeHash = ethAcct.GetCodeHash().Bytes() - } - return &statedb.Account{ Nonce: acct.GetSequence(), - CodeHash: codeHash, + CodeHash: k.GetAccountICodeHash(ctx, acct), } } diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index 1b24488338..6a3645ddd1 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -7,7 +7,6 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/evm/keeper" "github.com/EscanBE/evermint/v12/x/evm/statedb" evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" @@ -111,17 +110,17 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { expRes []int }{ { - "Only one account that's not a contract (no storage)", - func() {}, - []int{0}, + name: "Only one account that's not a contract (no storage)", + malleate: func() {}, + expRes: nil, // no contract, not any res }, { - "Two accounts - one contract (with storage), one wallet", - func() { + name: "Two accounts - one contract (with storage), one wallet", + malleate: func() { supply := big.NewInt(100) suite.DeployTestContract(suite.T(), suite.address, supply) }, - []int{2, 0}, + expRes: []int{2}, // the only contract }, } @@ -130,20 +129,22 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { suite.SetupTest() tc.malleate() i := 0 + countContracts := 0 suite.app.AccountKeeper.IterateAccounts(suite.ctx, func(account authtypes.AccountI) bool { - ethAccount, ok := account.(evertypes.EthAccountI) - if !ok { - // ignore non EthAccounts + if !suite.app.EvmKeeper.IsAccountIContractAccount(suite.ctx, account) { + // skip all non-contract accounts because the number of compatible accounts is now kinda unpredictable return false } - addr := ethAccount.EthAddress() + addr := common.BytesToAddress(account.GetAddress()) storage := suite.app.EvmKeeper.GetAccountStorage(suite.ctx, addr) - suite.Require().Equal(tc.expRes[i], len(storage)) + suite.Equal(tc.expRes[i], len(storage)) i++ + countContracts++ return false }) + suite.Equal(len(tc.expRes), countContracts) }) } } From 62c7e6636951f07abde58bfb8adea87badfa12e2 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 04:00:39 +0700 Subject: [PATCH 12/16] use BaseAccount instead of EthAccount in utils_test --- x/claims/keeper/utils_test.go | 9 ++------- x/feemarket/keeper/utils_test.go | 12 +++--------- x/vesting/keeper/utils_test.go | 12 +++--------- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/x/claims/keeper/utils_test.go b/x/claims/keeper/utils_test.go index 1a0e19b23b..fb372f75a5 100644 --- a/x/claims/keeper/utils_test.go +++ b/x/claims/keeper/utils_test.go @@ -11,7 +11,6 @@ import ( "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/claims/types" evm "github.com/EscanBE/evermint/v12/x/evm/types" feemarkettypes "github.com/EscanBE/evermint/v12/x/feemarket/types" @@ -23,7 +22,6 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) @@ -108,11 +106,8 @@ func (suite *KeeperTestSuite) CommitAfter(t time.Duration) { suite.queryClientEvm = evm.NewQueryClient(queryHelperEvm) } -func newEthAccount(baseAccount *authtypes.BaseAccount) evertypes.EthAccount { - return evertypes.EthAccount{ - BaseAccount: baseAccount, - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } +func newEthAccount(baseAccount *authtypes.BaseAccount) *authtypes.BaseAccount { + return baseAccount } func getAddr(priv *ethsecp256k1.PrivKey) sdk.AccAddress { diff --git a/x/feemarket/keeper/utils_test.go b/x/feemarket/keeper/utils_test.go index 0771744056..299e777e36 100644 --- a/x/feemarket/keeper/utils_test.go +++ b/x/feemarket/keeper/utils_test.go @@ -16,18 +16,15 @@ import ( stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - chainapp "github.com/EscanBE/evermint/v12/app" "github.com/EscanBE/evermint/v12/crypto/ethsecp256k1" "github.com/EscanBE/evermint/v12/encoding" "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/EscanBE/evermint/v12/x/feemarket/types" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" @@ -59,10 +56,7 @@ func (suite *KeeperTestSuite) SetupApp(checkTx bool) { types.RegisterQueryServer(queryHelper, suite.app.FeeMarketKeeper) suite.queryClient = types.NewQueryClient(queryHelper) - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) diff --git a/x/vesting/keeper/utils_test.go b/x/vesting/keeper/utils_test.go index 45ecd6d0a0..51c291d551 100644 --- a/x/vesting/keeper/utils_test.go +++ b/x/vesting/keeper/utils_test.go @@ -17,10 +17,6 @@ import ( stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/EscanBE/evermint/v12/app" cosmosante "github.com/EscanBE/evermint/v12/app/ante/cosmos" evmante "github.com/EscanBE/evermint/v12/app/ante/evm" @@ -29,10 +25,11 @@ import ( "github.com/EscanBE/evermint/v12/encoding" "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" epochstypes "github.com/EscanBE/evermint/v12/x/epochs/types" evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/EscanBE/evermint/v12/x/vesting/types" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" ) @@ -82,10 +79,7 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) { suite.app.EpochsKeeper.SetEpochInfo(suite.ctx, epoch) } - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) From 0040c38708091bbc8d91b29ec1822ce36bf46e1b Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 04:00:54 +0700 Subject: [PATCH 13/16] vesting now convert back to BaseAccount instead of EthAccount --- x/vesting/keeper/msg_server.go | 6 +----- x/vesting/keeper/msg_server_test.go | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index 201ac7e137..0cc21f7f2d 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -5,8 +5,6 @@ import ( "strconv" "time" - evertypes "github.com/EscanBE/evermint/v12/types" - "github.com/armon/go-metrics" errorsmod "cosmossdk.io/errors" @@ -302,9 +300,7 @@ func (k Keeper) ConvertVestingAccount( return nil, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "vesting coins still left in account: %s", msg.VestingAddress) } - ethAccount := evertypes.ProtoAccount().(*evertypes.EthAccount) - ethAccount.BaseAccount = vestingAcc.BaseAccount - k.accountKeeper.SetAccount(ctx, ethAccount) + k.accountKeeper.SetAccount(ctx, vestingAcc.BaseAccount) return &types.MsgConvertVestingAccountResponse{}, nil } diff --git a/x/vesting/keeper/msg_server_test.go b/x/vesting/keeper/msg_server_test.go index 690b9c010d..6b9deff88c 100644 --- a/x/vesting/keeper/msg_server_test.go +++ b/x/vesting/keeper/msg_server_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "fmt" - evertypes "github.com/EscanBE/evermint/v12/types" vestingexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" "time" @@ -578,7 +577,7 @@ func (suite *KeeperTestSuite) TestConvertVestingAccount() { _, ok := account.(vestingexported.VestingAccount) suite.Require().False(ok) - _, ok = account.(evertypes.EthAccountI) + _, ok = account.(*authtypes.BaseAccount) suite.Require().True(ok) } else { From 999c6ca4d780fd2c0556927f84c6b69e3161d36f Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 04:07:48 +0700 Subject: [PATCH 14/16] fix implementation & testcases for deprecated module `x/claims` --- x/claims/keeper/abci.go | 6 +++--- x/claims/keeper/abci_test.go | 25 +++++++------------------ x/claims/keeper/claim_test.go | 10 ++-------- 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/x/claims/keeper/abci.go b/x/claims/keeper/abci.go index bd51bfeb26..c9b585444b 100644 --- a/x/claims/keeper/abci.go +++ b/x/claims/keeper/abci.go @@ -1,10 +1,10 @@ package keeper import ( + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "strconv" errorsmod "cosmossdk.io/errors" - evertypes "github.com/EscanBE/evermint/v12/types" sdk "github.com/cosmos/cosmos-sdk/types" vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" @@ -117,8 +117,8 @@ func (k Keeper) ClawbackEmptyAccounts(ctx sdk.Context, claimsDenom string) { return false } - // ignore non ETH accounts - if _, isEthAccount := acc.(evertypes.EthAccountI); !isEthAccount { + // ignore module accounts + if _, isModuleAccount := acc.(authtypes.ModuleAccountI); isModuleAccount { return false } diff --git a/x/claims/keeper/abci_test.go b/x/claims/keeper/abci_test.go index e586955360..9fa7cb6285 100644 --- a/x/claims/keeper/abci_test.go +++ b/x/claims/keeper/abci_test.go @@ -6,14 +6,11 @@ import ( testutil "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" "github.com/EscanBE/evermint/v12/x/claims/types" vestingtypes "github.com/EscanBE/evermint/v12/x/vesting/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" ) func (suite *KeeperTestSuite) TestEndBlock() { @@ -116,8 +113,8 @@ func (suite *KeeperTestSuite) TestClawbackEmptyAccounts() { }, }, { - "balance non zero, base account is ignored", - 0, + "balance non zero, base account is accepted", + types.GenesisDust, func() { suite.app.AccountKeeper.SetAccount(suite.ctx, authtypes.NewBaseAccount(addr, nil, 0, 0)) @@ -145,11 +142,7 @@ func (suite *KeeperTestSuite) TestClawbackEmptyAccounts() { types.GenesisDust, func() { baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0) - ethAccount := evertypes.EthAccount{ - BaseAccount: baseAccount, - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } - suite.app.AccountKeeper.SetAccount(suite.ctx, ðAccount) + suite.app.AccountKeeper.SetAccount(suite.ctx, baseAccount) coins := sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, sdk.NewInt(types.GenesisDust))) err := testutil.FundAccount(suite.ctx, suite.app.BankKeeper, addr, coins) @@ -185,8 +178,7 @@ func (suite *KeeperTestSuite) TestClawbackEmptyAccounts() { "multiple denoms, only claims denom is clawed back", types.GenesisDust, func() { - ethAccount := newEthAccount(authtypes.NewBaseAccount(addr, nil, 0, 0)) - suite.app.AccountKeeper.SetAccount(suite.ctx, ðAccount) + suite.app.AccountKeeper.SetAccount(suite.ctx, authtypes.NewBaseAccount(addr, nil, 0, 0)) coin1 := sdk.NewCoin("testcoin", sdk.NewInt(types.GenesisDust)) coin2 := sdk.NewCoin("testcoin1", sdk.NewInt(types.GenesisDust)) @@ -204,12 +196,9 @@ func (suite *KeeperTestSuite) TestClawbackEmptyAccounts() { "multiple accounts, all clawed back", types.GenesisDust * 3, func() { - ethAccount1 := newEthAccount(authtypes.NewBaseAccount(addr, nil, 0, 0)) - ethAccount2 := newEthAccount(authtypes.NewBaseAccount(addr, nil, 0, 0)) - ethAccount3 := newEthAccount(authtypes.NewBaseAccount(addr, nil, 0, 0)) - suite.app.AccountKeeper.SetAccount(suite.ctx, ðAccount1) - suite.app.AccountKeeper.SetAccount(suite.ctx, ðAccount2) - suite.app.AccountKeeper.SetAccount(suite.ctx, ðAccount3) + suite.app.AccountKeeper.SetAccount(suite.ctx, newEthAccount(authtypes.NewBaseAccount(addr, nil, 0, 0))) + suite.app.AccountKeeper.SetAccount(suite.ctx, newEthAccount(authtypes.NewBaseAccount(addr2, nil, 0, 0))) + suite.app.AccountKeeper.SetAccount(suite.ctx, newEthAccount(authtypes.NewBaseAccount(addr3, nil, 0, 0))) coins := sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, sdk.NewInt(types.GenesisDust))) err := testutil.FundAccount(suite.ctx, suite.app.BankKeeper, addr, coins) diff --git a/x/claims/keeper/claim_test.go b/x/claims/keeper/claim_test.go index 675d1cc0d4..8268180c59 100644 --- a/x/claims/keeper/claim_test.go +++ b/x/claims/keeper/claim_test.go @@ -10,16 +10,13 @@ import ( "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" evertypes "github.com/EscanBE/evermint/v12/types" + "github.com/EscanBE/evermint/v12/x/claims/types" inflationtypes "github.com/EscanBE/evermint/v12/x/inflation/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - - "github.com/EscanBE/evermint/v12/x/claims/types" ) func (suite *KeeperTestSuite) TestGetClaimableAmountForAction() { @@ -1078,10 +1075,7 @@ func (suite *KeeperTestSuite) TestClawbackEmptyAccountsAirdrop() { addr, err := sdk.AccAddressFromBech32(tc.address) suite.Require().NoError(err, tc.name) - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(addr.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(addr.Bytes()), nil, 0, 0) err = acc.SetSequence(tc.sequence) suite.Require().NoError(err, tc.name) From b18bea35a0cf6c7f09d97805600b54828fac4c20 Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 04:13:20 +0700 Subject: [PATCH 15/16] fix implementation & testcases for deprecated module `x/incentives` --- x/incentives/keeper/evm_hooks.go | 4 +--- x/incentives/keeper/evm_hooks_test.go | 17 ++++------------- x/incentives/keeper/integration_test.go | 12 ++---------- x/incentives/keeper/utils_test.go | 6 +----- x/incentives/types/interfaces.go | 1 + 5 files changed, 9 insertions(+), 31 deletions(-) diff --git a/x/incentives/keeper/evm_hooks.go b/x/incentives/keeper/evm_hooks.go index 0f9b4ae570..05caf5682f 100644 --- a/x/incentives/keeper/evm_hooks.go +++ b/x/incentives/keeper/evm_hooks.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" - evertypes "github.com/EscanBE/evermint/v12/types" evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/EscanBE/evermint/v12/x/incentives/types" @@ -46,8 +45,7 @@ func (k Keeper) PostTxProcessing(ctx sdk.Context, msg core.Message, receipt *eth return nil } - ethAccount, ok := acc.(evertypes.EthAccountI) - if ok && ethAccount.Type() == evertypes.AccountTypeContract { + if k.evmKeeper.IsAccountIContractAccount(ctx, acc) { return nil } diff --git a/x/incentives/keeper/evm_hooks_test.go b/x/incentives/keeper/evm_hooks_test.go index df69593a92..2d64d78592 100644 --- a/x/incentives/keeper/evm_hooks_test.go +++ b/x/incentives/keeper/evm_hooks_test.go @@ -12,7 +12,6 @@ import ( "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" evm "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/EscanBE/evermint/v12/x/incentives/types" vestingtypes "github.com/EscanBE/evermint/v12/x/vesting/types" @@ -40,10 +39,8 @@ func (suite *KeeperTestSuite) TestEvmHooksStoreTxGasUsed() { "from address is not an EOA", func(contractAddr common.Address) { // set a contract account for the address - contract := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256([]byte{0, 1, 2, 2})).String(), - } + contract := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) + suite.app.EvmKeeper.SetAccountICodeHash(suite.ctx, contract, crypto.Keccak256([]byte{0, 1, 2, 2})) suite.app.AccountKeeper.SetAccount(suite.ctx, contract) res := suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(1000)) @@ -54,10 +51,7 @@ func (suite *KeeperTestSuite) TestEvmHooksStoreTxGasUsed() { { "correct execution - one tx", func(contractAddr common.Address) { - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) res := suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(1000)) @@ -94,10 +88,7 @@ func (suite *KeeperTestSuite) TestEvmHooksStoreTxGasUsed() { { "correct execution - two tx", func(contractAddr common.Address) { - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) res := suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(500)) diff --git a/x/incentives/keeper/integration_test.go b/x/incentives/keeper/integration_test.go index 3e30508b65..3f5fc5d6ba 100644 --- a/x/incentives/keeper/integration_test.go +++ b/x/incentives/keeper/integration_test.go @@ -12,9 +12,6 @@ import ( "github.com/ethereum/go-ethereum/common" - evertypes "github.com/EscanBE/evermint/v12/types" - evmtypes "github.com/EscanBE/evermint/v12/x/evm/types" - "github.com/EscanBE/evermint/v12/x/incentives/types" ) @@ -70,19 +67,14 @@ var _ = Describe("Distribution", Ordered, func() { s.Require().NoError(err) // set a EOA account for the address - eoa := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(s.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).String(), - } + eoa := authtypes.NewBaseAccount(sdk.AccAddress(s.address.Bytes()), nil, 0, 0) s.app.AccountKeeper.RemoveAccount(s.ctx, eoa) s.app.AccountKeeper.SetAccount(s.ctx, eoa) acc := s.app.AccountKeeper.GetAccount(s.ctx, s.address.Bytes()) s.Require().NotNil(acc) - ethAccount, ok := acc.(evertypes.EthAccountI) - s.Require().True(ok) - s.Require().Equal(evertypes.AccountTypeEOA, ethAccount.Type()) + s.Require().False(s.app.EvmKeeper.IsContractAccount(s.ctx, s.address)) contractAddr = contract moduleAcc = s.app.AccountKeeper.GetModuleAddress(types.ModuleName) diff --git a/x/incentives/keeper/utils_test.go b/x/incentives/keeper/utils_test.go index cf51f2d4b0..eb3d4324e4 100644 --- a/x/incentives/keeper/utils_test.go +++ b/x/incentives/keeper/utils_test.go @@ -15,7 +15,6 @@ import ( "github.com/EscanBE/evermint/v12/server/config" "github.com/EscanBE/evermint/v12/testutil" utiltx "github.com/EscanBE/evermint/v12/testutil/tx" - evertypes "github.com/EscanBE/evermint/v12/types" epochstypes "github.com/EscanBE/evermint/v12/x/epochs/types" evm "github.com/EscanBE/evermint/v12/x/evm/types" "github.com/EscanBE/evermint/v12/x/incentives/types" @@ -104,10 +103,7 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) { suite.app.EpochsKeeper.SetEpochInfo(suite.ctx, epoch) } - acc := &evertypes.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), - CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(), - } + acc := authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) // fund signer acc to pay for tx fees diff --git a/x/incentives/types/interfaces.go b/x/incentives/types/interfaces.go index 026b6815cb..4aa73599af 100644 --- a/x/incentives/types/interfaces.go +++ b/x/incentives/types/interfaces.go @@ -58,6 +58,7 @@ type InflationKeeper interface { type EVMKeeper interface { GetParams(ctx sdk.Context) evmtypes.Params GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account + IsAccountIContractAccount(ctx sdk.Context, account authtypes.AccountI) bool } // Stakekeeper defines the expected staking keeper interface used on incentives From 2c1980599e2e295062ceede5558386d0ef14471d Mon Sep 17 00:00:00 2001 From: VictorTrustyDev Date: Thu, 4 Jan 2024 04:42:20 +0700 Subject: [PATCH 16/16] prove empty code hash wastes storage --- x/evm/types/code_hash_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/evm/types/code_hash_test.go b/x/evm/types/code_hash_test.go index 5016db6fbb..cd914b940c 100644 --- a/x/evm/types/code_hash_test.go +++ b/x/evm/types/code_hash_test.go @@ -2,6 +2,7 @@ package types import ( "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" "reflect" "testing" ) @@ -73,3 +74,8 @@ func TestCodeHash_Bytes(t *testing.T) { }) } } + +func TestCodeHash_ProveEmptyCodeHashWastesStore(t *testing.T) { + require.NotEmpty(t, EmptyCodeHash) + require.Len(t, EmptyCodeHash, 32) +}