ante: check that sender is a EOA (#125)

* ante: check that sender is a EOA

* fix: GetCodeSize handles nil case and comments

* docs: add TODO comment

* fix: use EmptyCodeHash check

* lint: evmtypes instead of types

* lint: fix suite error

* test: set code to act not as EOA

* undo comment on GetCodeSize

* keeper: fix input checks

* Apply suggestions from code review

Co-authored-by: Akash Khosla <me@akashkhosla.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
hello-bwhour 2021-06-16 01:39:41 +08:00 committed by GitHub
parent d3c5df9dda
commit d7da045fc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 5 deletions

View File

@ -28,6 +28,7 @@ type EVMKeeper interface {
WithContext(ctx sdk.Context) WithContext(ctx sdk.Context)
ResetRefundTransient(ctx sdk.Context) ResetRefundTransient(ctx sdk.Context)
NewEVM(msg core.Message, config *params.ChainConfig) *vm.EVM NewEVM(msg core.Message, config *params.ChainConfig) *vm.EVM
GetCodeHash(addr common.Address) common.Hash
} }
// EthSigVerificationDecorator validates an ethereum signatures // EthSigVerificationDecorator validates an ethereum signatures
@ -126,7 +127,7 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
// get and set account must be called with an infinite gas meter in order to prevent // get and set account must be called with an infinite gas meter in order to prevent
// additional gas from being deducted. // additional gas from being deducted.
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
avd.evmKeeper.WithContext(infCtx)
evmDenom := avd.evmKeeper.GetParams(infCtx).EvmDenom evmDenom := avd.evmKeeper.GetParams(infCtx).EvmDenom
for i, msg := range tx.GetMsgs() { for i, msg := range tx.GetMsgs() {
@ -147,6 +148,14 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
) )
} }
// check whether the sender address is EOA
fromAddr := common.BytesToAddress(from)
codeHash := avd.evmKeeper.GetCodeHash(fromAddr)
if codeHash != common.BytesToHash(evmtypes.EmptyCodeHash) {
return ctx, stacktrace.Propagate(sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
"the sender is not EOA: address <%v>, codeHash <%s>", fromAddr, codeHash), "")
}
acc := avd.ak.GetAccount(infCtx, from) acc := avd.ak.GetAccount(infCtx, from)
if acc == nil { if acc == nil {
acc = avd.ak.NewAccountWithAddress(infCtx, from) acc = avd.ak.NewAccountWithAddress(infCtx, from)
@ -164,8 +173,10 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
"sender should have had enough funds to pay for tx cost = fee + amount (%s = %s + amount)", msgEthTx.Cost(), msgEthTx.Fee(), "sender should have had enough funds to pay for tx cost = fee + amount (%s = %s + amount)", msgEthTx.Cost(), msgEthTx.Fee(),
) )
} }
}
}
// recover the original gas meter
avd.evmKeeper.WithContext(ctx)
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }

View File

@ -86,10 +86,23 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
true, true,
false, false,
}, },
{
"sender not EOA",
tx,
func() {
// set not as an EOA
suite.app.EvmKeeper.SetCode(addr, []byte("1"))
},
true,
false,
},
{ {
"not enough balance to cover tx cost", "not enough balance to cover tx cost",
tx, tx,
func() {}, func() {
// reset back to EOA
suite.app.EvmKeeper.SetCode(addr, nil)
},
true, true,
false, false,
}, },

View File

@ -86,6 +86,7 @@ func (suite *AnteTestSuite) CreateTestTx(
suite.Require().NoError(err) suite.Require().NoError(err)
err = builder.SetMsgs(msg) err = builder.SetMsgs(msg)
suite.Require().NoError(err)
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(msg.Fee()))) fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(msg.Fee())))
builder.SetFeeAmount(fees) builder.SetFeeAmount(fees)
builder.SetGasLimit(msg.GetGas()) builder.SetGasLimit(msg.GetGas())

View File

@ -228,6 +228,9 @@ func (k *Keeper) GetCode(addr common.Address) []byte {
// SetCode calls CommitStateDB.SetCode using the passed in context // SetCode calls CommitStateDB.SetCode using the passed in context
func (k *Keeper) SetCode(addr common.Address, code []byte) { func (k *Keeper) SetCode(addr common.Address, code []byte) {
if bytes.Equal(code, types.EmptyCodeHash) {
k.Logger(k.ctx).Debug("passed in EmptyCodeHash, but expected empty code")
}
hash := crypto.Keccak256Hash(code) hash := crypto.Keccak256Hash(code)
// update account code hash // update account code hash
@ -269,9 +272,11 @@ func (k *Keeper) SetCode(addr common.Address, code []byte) {
) )
} }
// GetCodeSize returns the code hash stored in the address account. // GetCodeSize returns the size of the contract code associated with this object,
// or zero if none.
func (k *Keeper) GetCodeSize(addr common.Address) int { func (k *Keeper) GetCodeSize(addr common.Address) int {
return len(k.GetCode(addr)) code := k.GetCode(addr)
return len(code)
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------