Skip to content
This repository has been archived by the owner on Jun 9, 2024. It is now read-only.

fix(precompile): Fix regression where eth_call can cause non-deterministic gas consumption #1136

Merged
merged 12 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cosmos/x/evm/keeper/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (h *host) Setup(
) {
// Setup the state, precompile, historical, and txpool plugins
h.sp = state.NewPlugin(ak, storeKey, log.NewFactory(h.pcs().GetPrecompiles()))
h.pp = precompile.NewPlugin(h.pcs().GetPrecompiles(), h.sp)
h.pp = precompile.NewPlugin(h.pcs().GetPrecompiles())
// TODO: re-enable historical plugin using ABCI listener.
h.hp = historical.NewPlugin(h.cp, h.bp, nil, storeKey)
h.txp.SetNonceRetriever(h.sp)
Expand Down
11 changes: 1 addition & 10 deletions cosmos/x/evm/plugins/precompile/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,15 @@ type plugin struct {
kvGasConfig storetypes.GasConfig
// transientKVGasConfig is the gas config for the transient KV store.
transientKVGasConfig storetypes.GasConfig
// sp allows resetting the context for the reentrancy into the EVM.
sp StatePlugin
}

// NewPlugin creates and returns a plugin with the default KV store gas configs.
func NewPlugin(precompiles []ethprecompile.Registrable, sp StatePlugin) Plugin {
func NewPlugin(precompiles []ethprecompile.Registrable) Plugin {
return &plugin{
Registry: registry.NewMap[common.Address, vm.PrecompileContainer](),
precompiles: precompiles,
kvGasConfig: storetypes.KVGasConfig(),
transientKVGasConfig: storetypes.TransientGasConfig(),
sp: sp,
}
}

Expand Down Expand Up @@ -185,9 +182,6 @@ func (p *plugin) enableReentrancy(sdb vm.PolarisStateDB) {
// end precompile execution => stop emitting Cosmos event as Eth logs for now
cem := utils.MustGetAs[state.ControllableEventManager](sdkCtx.EventManager())
cem.EndPrecompileExecution()

// remove Cosmos gas consumption so gas is consumed only per OPCODE
p.sp.SetGasConfig(storetypes.GasConfig{}, storetypes.GasConfig{})
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
}

// DisableReentrancy sets the state so that execution cannot enter the EVM again.
Expand All @@ -203,7 +197,4 @@ func (p *plugin) disableReentrancy(sdb vm.PolarisStateDB) {
// resume precompile execution => begin emitting Cosmos event as Eth logs again
cem := utils.MustGetAs[state.ControllableEventManager](sdkCtx.EventManager())
cem.BeginPrecompileExecution(sdb)

// restore ctx gas configs for continuing precompile execution
p.sp.SetGasConfig(p.kvGasConfig, p.transientKVGasConfig)
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
}
10 changes: 1 addition & 9 deletions cosmos/x/evm/plugins/precompile/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var _ = Describe("plugin", func() {
ctx = ctx.WithEventManager(
events.NewManagerFrom(ctx.EventManager(), mock.NewPrecompileLogFactory()),
)
p = utils.MustGetAs[*plugin](NewPlugin(nil, &mockSP{ctx}))
p = utils.MustGetAs[*plugin](NewPlugin(nil))
e = &mockEVM{nil, ctx, &mockSDB{nil, ctx, 0}}
})

Expand Down Expand Up @@ -125,14 +125,6 @@ var (

// MOCKS BELOW.

type mockSP struct {
ctx sdk.Context
}

func (msp *mockSP) SetGasConfig(kvg storetypes.GasConfig, tkvg storetypes.GasConfig) {
msp.ctx = msp.ctx.WithKVGasConfig(kvg).WithTransientKVGasConfig(tkvg)
}

type mockEVM struct {
vm.PrecompileEVM
ctx sdk.Context
Expand Down
10 changes: 3 additions & 7 deletions cosmos/x/evm/plugins/state/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ type Plugin interface {
IterateBalances(fn func(common.Address, *big.Int) bool)
// IterateState iterates over the state of all accounts and calls the given callback function.
IterateState(fn func(addr common.Address, key common.Hash, value common.Hash) bool)
// SetGasConfig sets the gas config for the plugin.
SetGasConfig(storetypes.GasConfig, storetypes.GasConfig)
}

// The StatePlugin is a very fun and interesting part of the EVM implementation. But if you want to
Expand Down Expand Up @@ -165,7 +163,7 @@ func (p *plugin) Reset(ctx context.Context) {
// and is designed to be used in a standalone manner, as each of the EVM's opcodes are priced
// individually. By setting the gas configs to empty structs, we ensure that SLOADS and SSTORES
// in the EVM are not being charged additional gas unknowingly.
p.SetGasConfig(storetypes.GasConfig{}, storetypes.GasConfig{})
p.setGasConfig(storetypes.GasConfig{}, storetypes.GasConfig{})

// We setup a snapshot controller to properly revert the Controllable MultiStore and EventManager.
p.Controller = snapshot.NewController[string, libtypes.Controllable[string]]()
Expand Down Expand Up @@ -540,9 +538,7 @@ func (p *plugin) Clone() ethstate.Plugin {
return sp
}

// SetGasConfig implements Plugin.
func (p *plugin) SetGasConfig(kvGasConfig, transientKVGasConfig storetypes.GasConfig) {
// setGasConfig sets the gas configuration for the kvstore.
func (p *plugin) setGasConfig(kvGasConfig, transientKVGasConfig storetypes.GasConfig) {
p.ctx = p.ctx.WithKVGasConfig(kvGasConfig).WithTransientKVGasConfig(transientKVGasConfig)
}

// IsPlugin implements plugins.Base.