From 9bc8d568df5f7970659a1a13c361cc591969ff60 Mon Sep 17 00:00:00 2001 From: MiniFrenchBread <103425574+MiniFrenchBread@users.noreply.github.com> Date: Sat, 28 Dec 2024 00:58:15 +0800 Subject: [PATCH] feat: precompile initialization --- precompiles/common/common.go | 60 ++++++++++++++++++++++++++++++ precompiles/dasigners/dasigners.go | 41 +++----------------- precompiles/staking/staking.go | 31 +++------------ 3 files changed, 72 insertions(+), 60 deletions(-) create mode 100644 precompiles/common/common.go diff --git a/precompiles/common/common.go b/precompiles/common/common.go new file mode 100644 index 00000000..dcc52eae --- /dev/null +++ b/precompiles/common/common.go @@ -0,0 +1,60 @@ +package common + +import ( + "fmt" + + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/evmos/ethermint/x/evm/statedb" +) + +type PrecompileCommon interface { + Abi() *abi.ABI + IsTx(string) bool +} + +func InitializePrecompileCall( + p PrecompileCommon, + evm *vm.EVM, + contract *vm.Contract, + readonly bool, +) ( + ctx sdk.Context, + stateDB *statedb.StateDB, + method *abi.Method, + initialGas storetypes.Gas, + args []interface{}, + err error, +) { + // parse input + if len(contract.Input) < 4 { + return sdk.Context{}, nil, nil, uint64(0), nil, vm.ErrExecutionReverted + } + method, err = p.Abi().MethodById(contract.Input[:4]) + if err != nil { + return sdk.Context{}, nil, nil, uint64(0), nil, vm.ErrExecutionReverted + } + args, err = method.Inputs.Unpack(contract.Input[4:]) + if err != nil { + return sdk.Context{}, nil, nil, uint64(0), nil, err + } + // readonly check + if readonly && p.IsTx(method.Name) { + return sdk.Context{}, nil, nil, uint64(0), nil, fmt.Errorf(ErrWriteOnReadOnly) + } + // get state db and context + stateDB, ok := evm.StateDB.(*statedb.StateDB) + if !ok { + return sdk.Context{}, nil, nil, uint64(0), nil, fmt.Errorf(ErrGetStateDB) + } + ctx, err = stateDB.GetCachedContextForPrecompile() + if err != nil { + return sdk.Context{}, nil, nil, uint64(0), nil, err + } + // initial gas + initialGas = ctx.GasMeter().GasConsumed() + + return ctx, stateDB, method, initialGas, args, nil +} diff --git a/precompiles/dasigners/dasigners.go b/precompiles/dasigners/dasigners.go index 6e0a6a88..3fc60aa5 100644 --- a/precompiles/dasigners/dasigners.go +++ b/precompiles/dasigners/dasigners.go @@ -1,16 +1,13 @@ package dasigners import ( - "fmt" "strings" precompiles_common "github.com/0glabs/0g-chain/precompiles/common" dasignerskeeper "github.com/0glabs/0g-chain/x/dasigners/v1/keeper" - storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - "github.com/evmos/ethermint/x/evm/statedb" ) const ( @@ -47,17 +44,8 @@ var RequiredGasBasic = map[string]uint64{ DASignersFunctionRegisteredEpoch: 10000, } -var KVGasConfig storetypes.GasConfig = storetypes.GasConfig{ - HasCost: 0, - DeleteCost: 0, - ReadCostFlat: 0, - ReadCostPerByte: 0, - WriteCostFlat: 0, - WriteCostPerByte: 0, - IterNextCostFlat: 0, -} - var _ vm.PrecompiledContract = &DASignersPrecompile{} +var _ precompiles_common.PrecompileCommon = &DASignersPrecompile{} type DASignersPrecompile struct { abi abi.ABI @@ -103,33 +91,16 @@ func (d *DASignersPrecompile) IsTx(method string) bool { } } +func (d *DASignersPrecompile) Abi() *abi.ABI { + return &d.abi +} + // Run implements vm.PrecompiledContract. func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { - // parse input - if len(contract.Input) < 4 { - return nil, vm.ErrExecutionReverted - } - method, err := d.abi.MethodById(contract.Input[:4]) - if err != nil { - return nil, vm.ErrExecutionReverted - } - args, err := method.Inputs.Unpack(contract.Input[4:]) + ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(d, evm, contract, readonly) if err != nil { return nil, err } - // readonly check - if readonly && d.IsTx(method.Name) { - return nil, fmt.Errorf(precopmiles_common.ErrWriteOnReadOnly) - } - // get state db and context - stateDB, ok := evm.StateDB.(*statedb.StateDB) - if !ok { - return nil, fmt.Errorf(precompiles_common.ErrGetStateDB) - } - ctx := stateDB.GetContext() - // reset gas config - ctx = ctx.WithKVGasConfig(KVGasConfig) - initialGas := ctx.GasMeter().GasConsumed() var bz []byte switch method.Name { diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 3543e7f2..7fb6f375 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -1,16 +1,13 @@ package staking import ( - "fmt" "strings" precompiles_common "github.com/0glabs/0g-chain/precompiles/common" - "github.com/cosmos/cosmos-sdk/store/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - "github.com/evmos/ethermint/x/evm/statedb" ) const ( @@ -40,6 +37,7 @@ const ( ) var _ vm.PrecompiledContract = &StakingPrecompile{} +var _ precompiles_common.PrecompileCommon = &StakingPrecompile{} type StakingPrecompile struct { abi abi.ABI @@ -67,6 +65,10 @@ func (s *StakingPrecompile) RequiredGas(input []byte) uint64 { return 0 } +func (s *StakingPrecompile) Abi() *abi.ABI { + return &s.abi +} + func (s *StakingPrecompile) IsTx(method string) bool { switch method { case StakingFunctionCreateValidator, @@ -83,31 +85,10 @@ func (s *StakingPrecompile) IsTx(method string) bool { // Run implements vm.PrecompiledContract. func (s *StakingPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { - // parse input - if len(contract.Input) < 4 { - return nil, vm.ErrExecutionReverted - } - method, err := s.abi.MethodById(contract.Input[:4]) - if err != nil { - return nil, vm.ErrExecutionReverted - } - args, err := method.Inputs.Unpack(contract.Input[4:]) + ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(s, evm, contract, readonly) if err != nil { return nil, err } - // readonly check - if readonly && s.IsTx(method.Name) { - return nil, fmt.Errorf(precopmiles_common.ErrWriteOnReadOnly) - } - // get state db and context - stateDB, ok := evm.StateDB.(*statedb.StateDB) - if !ok { - return nil, fmt.Errorf(precompiles_common.ErrGetStateDB) - } - ctx := stateDB.GetContext() - // reset gas config - ctx = ctx.WithKVGasConfig(types.KVGasConfig()) - initialGas := ctx.GasMeter().GasConsumed() var bz []byte switch method.Name {