Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FVM] beyond EVM part 2.2 - adding EVM emulator #4927

Merged
merged 28 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
01bc52e
add emulator code
ramtinms Nov 2, 2023
c5ec8b2
go mod tidy
ramtinms Nov 2, 2023
0306c55
.
ramtinms Nov 2, 2023
14f56a1
fix test
ramtinms Nov 2, 2023
3ea815d
Merge branch 'ramtin/evm-adding-emulator-database' into ramtin/evm-ad…
ramtinms Nov 2, 2023
a21ecbe
update commit
ramtinms Nov 2, 2023
76686d3
minor improvements
ramtinms Nov 3, 2023
7395887
simplify direct calls
ramtinms Nov 3, 2023
e205b2a
add EVM validation error type
ramtinms Nov 3, 2023
5ee4bc4
Merge branch 'ramtin/evm-adding-emulator-database' into ramtin/evm-ad…
ramtinms Nov 3, 2023
d0328c4
typo
ramtinms Nov 3, 2023
6a9fee2
fix error handling
ramtinms Nov 3, 2023
f3d9a25
.
ramtinms Nov 3, 2023
57d342b
.
ramtinms Nov 3, 2023
b98e919
add more tests on tx validation
ramtinms Nov 3, 2023
c0c6844
doc
ramtinms Nov 3, 2023
948fd28
update docs
ramtinms Nov 3, 2023
1a8e3dd
doc update
ramtinms Nov 3, 2023
3ed4ea2
improve error handling
ramtinms Nov 3, 2023
eb152e1
apply PR comments
ramtinms Nov 6, 2023
26480ec
apply PR comments
ramtinms Nov 6, 2023
ae39807
Merge branch 'master' into ramtin/evm-adding-emulator
ramtinms Nov 6, 2023
3594345
fix err override issue
ramtinms Nov 6, 2023
03a064e
Merge branch 'master' into ramtin/evm-adding-emulator
ramtinms Nov 7, 2023
81e7c4d
Merge branch 'master' into ramtin/evm-adding-emulator
ramtinms Nov 7, 2023
c848b92
apply PR feedback
ramtinms Nov 7, 2023
48be317
remove WithBaseFee config
ramtinms Nov 7, 2023
cda7ba4
Merge branch 'master' into ramtin/evm-adding-emulator
ramtinms Nov 7, 2023
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
183 changes: 183 additions & 0 deletions fvm/evm/emulator/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package emulator

import (
"math"
"math/big"

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

var (
FlowEVMTestnetChainID = big.NewInt(666)
FlowEVMMainnetChainID = big.NewInt(777)
BlockLevelGasLimit = uint64(math.MaxUint64)
zero = uint64(0)
)

// Config sets the required parameters
type Config struct {
// Chain Config
ChainConfig *params.ChainConfig
// EVM config
EVMConfig vm.Config
// block context
BlockContext *vm.BlockContext
// transaction context
TxContext *vm.TxContext
// base unit of gas for direct calls
DirectCallBaseGasUsage uint64
}

// DefaultChainConfig is the default chain config which
// considers majority of EVM upgrades (e.g. Shanghai update) already been applied
// this has done through setting the height of these changes
// to zero nad setting the time for some other changes to zero
// For the future changes of EVM, we need to update the EVM go mod version
// and set a proper height for the specific release based on the Flow EVM heights
// so it could gets activated at a desired time.
var DefaultChainConfig = &params.ChainConfig{
ChainID: FlowEVMTestnetChainID, // default is testnet

// Fork scheduling based on block heights
HomesteadBlock: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
DAOForkSupport: false,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), // already on Byzantium
ConstantinopleBlock: big.NewInt(0), // already on Constantinople
PetersburgBlock: big.NewInt(0), // already on Petersburg
IstanbulBlock: big.NewInt(0), // already on Istanbul
BerlinBlock: big.NewInt(0), // already on Berlin
LondonBlock: big.NewInt(0), // already on London
MuirGlacierBlock: big.NewInt(0), // already on MuirGlacier

// Fork scheduling based on timestamps
ShanghaiTime: &zero, // already on Shanghai
CancunTime: &zero, // already on Cancun
PragueTime: &zero, // already on Prague
}

func defaultConfig() *Config {
return &Config{
ChainConfig: DefaultChainConfig,
EVMConfig: vm.Config{
NoBaseFee: true,
},
TxContext: &vm.TxContext{},
BlockContext: &vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
GasLimit: BlockLevelGasLimit, // block gas limit
BaseFee: big.NewInt(0), //
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
BaseFee: big.NewInt(0), //
BaseFee: big.NewInt(0),

GetHash: func(n uint64) common.Hash { // default returns some random hash values
return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
},
},
}
}

// NewConfig initializes a new config
func NewConfig(opts ...Option) *Config {
ctx := defaultConfig()
for _, applyOption := range opts {
ctx = applyOption(ctx)
}
return ctx
}

type Option func(*Config) *Config

// WithMainnetChainID sets the chain ID to flow evm testnet
func WithTestnetChainID() Option {
return func(c *Config) *Config {
c.ChainConfig.ChainID = FlowEVMTestnetChainID
return c
}
}

// WithMainnetChainID sets the chain ID to flow evm mainnet
func WithMainnetChainID() Option {
return func(c *Config) *Config {
c.ChainConfig.ChainID = FlowEVMMainnetChainID
return c
}

}

// WithOrigin sets the origin of the transaction (signer)
func WithOrigin(origin common.Address) Option {
return func(c *Config) *Config {
c.TxContext.Origin = origin
return c
}
}

// WithGasPrice sets the gas price for the transaction (usually the one sets by the sender)
func WithGasPrice(gasPrice *big.Int) Option {
return func(c *Config) *Config {
c.TxContext.GasPrice = gasPrice
return c
}
}

// WithBaseFee sets the the base fee for each transaction
func WithBaseFee(baseFee *big.Int) Option {
return func(c *Config) *Config {
c.BlockContext.BaseFee = baseFee
return c
}
}

// WithGasLimit sets the gas limit of the transaction
func WithGasLimit(gasLimit uint64) Option {
return func(c *Config) *Config {
c.BlockContext.GasLimit = gasLimit
return c
}
}

// WithCoinbase sets the coinbase of the block where the fees are collected in
func WithCoinbase(coinbase common.Address) Option {
return func(c *Config) *Config {
c.BlockContext.Coinbase = coinbase
return c
}
}

// WithBlockNumber sets the block height in the block context
func WithBlockNumber(blockNumber *big.Int) Option {
return func(c *Config) *Config {
c.BlockContext.BlockNumber = blockNumber
return c
}
}

// WithBlockTime sets the block time in the block context
func WithBlockTime(time uint64) Option {
return func(c *Config) *Config {
c.BlockContext.Time = time
return c
}
}

// WithGetBlockHashFunction sets the functionality to look up block hash by height
func WithGetBlockHashFunction(getHash vm.GetHashFunc) Option {
return func(c *Config) *Config {
c.BlockContext.GetHash = getHash
return c
}
}

// WithDirectCallBaseGasUsage sets the base direct call gas usage
func WithDirectCallBaseGasUsage(gas uint64) Option {
return func(c *Config) *Config {
c.DirectCallBaseGasUsage = gas
return c
}
}
1 change: 1 addition & 0 deletions fvm/evm/emulator/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ func handleError(err error) error {
return nil
}
var atreeFatalError *atree.FatalError
// if is a atree fatal error or fvm fatal error (the second one captures external errors)
if stdErrors.As(err, &atreeFatalError) || errors.IsFailure(err) {
return types.NewFatalError(err)
}
Expand Down
Loading