Skip to content

Commit

Permalink
refactor: evmConstructor
Browse files Browse the repository at this point in the history
* active pre-compiled contracts
  • Loading branch information
devon-chain committed Apr 17, 2023
1 parent a9c44fc commit 37bcec3
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 58 deletions.
28 changes: 14 additions & 14 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type Keeper struct {
hooks types.EvmHooks

// custom stateless precompiled smart contracts
customPrecompiles evm.PrecompiledContracts
getPrecompilesExtended func(ctx sdk.Context, evm *vm.EVM) evm.PrecompiledContracts

// evm constructor function
evmConstructor evm.Constructor
Expand All @@ -89,7 +89,7 @@ func NewKeeper(
bankKeeper types.BankKeeper,
sk types.StakingKeeper,
fmk types.FeeMarketKeeper,
customPrecompiles evm.PrecompiledContracts,
getPrecompilesExtended func(ctx sdk.Context, evm *vm.EVM) evm.PrecompiledContracts,
evmConstructor evm.Constructor,
tracer string,
ss paramstypes.Subspace,
Expand All @@ -106,18 +106,18 @@ func NewKeeper(

// NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations
return &Keeper{
cdc: cdc,
authority: authority,
accountKeeper: ak,
bankKeeper: bankKeeper,
stakingKeeper: sk,
feeMarketKeeper: fmk,
storeKey: storeKey,
transientKey: transientKey,
customPrecompiles: customPrecompiles,
evmConstructor: evmConstructor,
tracer: tracer,
ss: ss,
cdc: cdc,
authority: authority,
accountKeeper: ak,
bankKeeper: bankKeeper,
stakingKeeper: sk,
feeMarketKeeper: fmk,
storeKey: storeKey,
transientKey: transientKey,
getPrecompilesExtended: getPrecompilesExtended,
evmConstructor: evmConstructor,
tracer: tracer,
ss: ss,
}
}

Expand Down
2 changes: 1 addition & 1 deletion x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (k *Keeper) NewEVM(
tracer = k.Tracer(ctx, msg, cfg.ChainConfig)
}
vmConfig := k.VMConfig(ctx, msg, cfg, tracer)
return k.evmConstructor(blockCtx, txCtx, stateDB, cfg.ChainConfig, vmConfig, k.customPrecompiles)
return k.evmConstructor(ctx, blockCtx, txCtx, stateDB, cfg.ChainConfig, vmConfig, k.getPrecompilesExtended)
}

// GetHashFn implements vm.GetHashFunc for Ethermint. It handles 3 cases:
Expand Down
54 changes: 22 additions & 32 deletions x/evm/vm/geth/geth.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
package geth

import (
"math/big"
"bytes"
"sort"

"github.com/ethereum/go-ethereum/common"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"

Expand All @@ -39,16 +40,33 @@ type EVM struct {
// the default precompiled contracts and the EVM concrete implementation from
// geth.
func NewEVM(
ctx sdk.Context,
blockCtx vm.BlockContext,
txCtx vm.TxContext,
stateDB vm.StateDB,
chainConfig *params.ChainConfig,
config vm.Config,
_ evm.PrecompiledContracts, // unused
getPrecompilesExtended func(ctx sdk.Context, evm *vm.EVM) evm.PrecompiledContracts,
) evm.EVM {
return &EVM{
newEvm := &EVM{
EVM: vm.NewEVM(blockCtx, txCtx, stateDB, chainConfig, config),
}

precompiles := GetPrecompiles(chainConfig, blockCtx.BlockNumber)
activePrecompiles := GetActivePrecompiles(chainConfig, blockCtx.BlockNumber)

customPrecompiles := getPrecompilesExtended(ctx, newEvm.EVM)
for k, v := range customPrecompiles {
precompiles[k] = v
activePrecompiles = append(activePrecompiles, v.Address())
}

sort.SliceStable(activePrecompiles, func(i, j int) bool {
return bytes.Compare(activePrecompiles[i].Bytes(), activePrecompiles[j].Bytes()) < 0
})

newEvm.WithPrecompiles(precompiles, activePrecompiles)
return newEvm
}

// Context returns the EVM's Block Context
Expand All @@ -65,31 +83,3 @@ func (e EVM) TxContext() vm.TxContext {
func (e EVM) Config() vm.Config {
return e.EVM.Config
}

// Precompile returns the precompiled contract associated with the given address
// and the current chain configuration. If the contract cannot be found it returns
// nil.
func (e EVM) Precompile(addr common.Address) (p vm.PrecompiledContract, found bool) {
precompiles := GetPrecompiles(e.ChainConfig(), e.EVM.Context.BlockNumber)
p, found = precompiles[addr]
return p, found
}

// ActivePrecompiles returns a list of all the active precompiled contract addresses
// for the current chain configuration.
func (EVM) ActivePrecompiles(rules params.Rules) []common.Address {
return vm.DefaultActivePrecompiles(rules)
}

// RunPrecompiledContract runs a stateless precompiled contract and ignores the address and
// value arguments. It uses the RunPrecompiledContract function from the geth vm package.
func (e EVM) RunPrecompiledContract(
p vm.PrecompiledContract,
caller vm.ContractRef,
input []byte,
suppliedGas uint64,
value *big.Int, // value arg is unused
readOnly bool,
) (ret []byte, remainingGas uint64, err error) {
return e.EVM.RunPrecompiledContract(p, caller, input, suppliedGas, value, readOnly)
}
36 changes: 31 additions & 5 deletions x/evm/vm/geth/precompiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package geth
import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"

Expand All @@ -27,16 +28,41 @@ import (
// GetPrecompiles returns all the precompiled contracts defined given the
// current chain configuration and block height.
func GetPrecompiles(cfg *params.ChainConfig, blockNumber *big.Int) evm.PrecompiledContracts {
var precompiles evm.PrecompiledContracts
var defaulfPrecompiles evm.PrecompiledContracts
switch {
case cfg.IsBerlin(blockNumber):
precompiles = vm.PrecompiledContractsBerlin
defaulfPrecompiles = vm.PrecompiledContractsBerlin
case cfg.IsIstanbul(blockNumber):
precompiles = vm.PrecompiledContractsIstanbul
defaulfPrecompiles = vm.PrecompiledContractsIstanbul
case cfg.IsByzantium(blockNumber):
precompiles = vm.PrecompiledContractsByzantium
defaulfPrecompiles = vm.PrecompiledContractsByzantium
default:
precompiles = vm.PrecompiledContractsHomestead
defaulfPrecompiles = vm.PrecompiledContractsHomestead
}
precompiles := make(evm.PrecompiledContracts, len(defaulfPrecompiles))
for address, contract := range defaulfPrecompiles {
precompiles[address] = contract
}
return precompiles
}

// GetActivePrecompiles returns all the precompiled active contracts defined given the
// current chain configuration and block height.
func GetActivePrecompiles(cfg *params.ChainConfig, blockNumber *big.Int) []common.Address {
var defaultActivePrecompiles []common.Address
switch {
case cfg.IsBerlin(blockNumber):
defaultActivePrecompiles = vm.PrecompiledAddressesBerlin
case cfg.IsIstanbul(blockNumber):
defaultActivePrecompiles = vm.PrecompiledAddressesIstanbul
case cfg.IsByzantium(blockNumber):
defaultActivePrecompiles = vm.PrecompiledAddressesByzantium
default:
defaultActivePrecompiles = vm.PrecompiledAddressesHomestead
}

activePrecompiles := make([]common.Address, len(defaultActivePrecompiles))
copy(activePrecompiles, defaultActivePrecompiles)

return defaultActivePrecompiles
}
9 changes: 3 additions & 6 deletions x/evm/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package vm
import (
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
Expand All @@ -27,11 +28,6 @@ import (
// PrecompiledContracts defines a map of address -> precompiled contract
type PrecompiledContracts map[common.Address]vm.PrecompiledContract

type StatefulPrecompiledContract interface {
vm.PrecompiledContract
RunStateful(evm EVM, addr common.Address, input []byte, value *big.Int) (ret []byte, err error)
}

// EVM defines the interface for the Ethereum Virtual Machine used by the EVM module.
type EVM interface {
Config() vm.Config
Expand Down Expand Up @@ -73,10 +69,11 @@ type EVM interface {
// Constructor defines the function used to instantiate the EVM on
// each state transition.
type Constructor func(
ctx sdk.Context,
blockCtx vm.BlockContext,
txCtx vm.TxContext,
stateDB vm.StateDB,
chainConfig *params.ChainConfig,
config vm.Config,
customPrecompiles PrecompiledContracts,
getPrecompilesExtended func(ctx sdk.Context, evm *vm.EVM) PrecompiledContracts,
) EVM

0 comments on commit 37bcec3

Please sign in to comment.