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

wip: use libevm (params, core/vm) #1335

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
6d60741
wip: use libevm (params)
darioush Sep 5, 2024
d999563
base change
darioush Sep 6, 2024
1c7e25b
test unmarshal capability
darioush Sep 6, 2024
a119516
separate avalanche stuff to its own type
darioush Sep 6, 2024
25bb446
separate RulesExtra
darioush Sep 6, 2024
c371a3a
separate calls to extra
darioush Sep 6, 2024
9b27ebe
use darioush/access-list-for-hook
darioush Sep 9, 2024
784e2e6
config_extra: move methods off Rules/ChainConfig receivers
darioush Sep 9, 2024
a8a5c80
un-embed RulesExtra
darioush Sep 9, 2024
d74cea6
params: use gethparams.Rules
darioush Sep 9, 2024
ed1165b
unused
darioush Sep 9, 2024
e1088b1
update chainConfig.Rules callsites to pass params.IsMergeTODO
darioush Sep 10, 2024
846f52a
params/config: type alias ConfigCompatError
darioush Sep 10, 2024
932967d
bring in gethparams.ChainConfig (wip)
darioush Sep 10, 2024
053af95
params: add LondonBlock
darioush Sep 10, 2024
44db6c7
params: add ShanghaiTime
darioush Sep 10, 2024
cd5adc9
params: add BerlinBlock
darioush Sep 10, 2024
70659d3
params: unused code
darioush Sep 10, 2024
5d5fb59
reduce diff
darioush Sep 10, 2024
07203b0
update to darioush/json-root branch
darioush Sep 10, 2024
99c1b70
params: add IsLondon checks to Cancun (similar to upstream)
darioush Sep 10, 2024
e8febb8
race free impl for WithExtra, still hack
darioush Sep 11, 2024
04338c7
Merge branch 'master' of github.com:ava-labs/subnet-evm into use-libe…
darioush Sep 11, 2024
a5a43cc
use RulesExtra (instead of ptr)
darioush Sep 11, 2024
4a41e81
bump libevm
darioush Sep 11, 2024
5049989
bump libevm
darioush Sep 11, 2024
2a46ead
chain hooks for create
darioush Sep 11, 2024
672f54e
use geth forks in core/vm/evm.go
darioush Sep 11, 2024
7b8ec21
core/types, core/state: import gethparams
darioush Sep 12, 2024
f30f450
core/vm: use gethparams and hook in precompiles
darioush Sep 12, 2024
dc4b361
core/types: use upstream Log type
darioush Sep 12, 2024
5038b15
core/types: use upstream for AccessList
darioush Sep 12, 2024
dad843a
core/vm: use libevm
darioush Sep 12, 2024
0fe10ff
linting
darioush Sep 12, 2024
5b073ad
fix mockgen
darioush Sep 12, 2024
34a17a6
adjustment for libevm chainconfig changes
darioush Sep 12, 2024
73b5559
populate vm.BlockContext.Random as Difficulty starting at Durango (to…
darioush Sep 13, 2024
61b1694
nit
darioush Sep 13, 2024
8d2493f
Merge branch 'master' of github.com:ava-labs/subnet-evm into use-libe…
darioush Sep 17, 2024
12cd83e
update libevm
darioush Sep 17, 2024
20854a1
update libevm
darioush Sep 17, 2024
e9ee414
rebase to latest libevm (+ fix commit on darioush/json-root)
darioush Sep 24, 2024
61eb933
add support for custom upstream tag
darioush Sep 24, 2024
28caecc
remove eth/tracers subdirs
darioush Sep 24, 2024
86cdfbe
update geth-allowed-packages.txt
darioush Sep 24, 2024
f1d77d2
Merge branch 'master' of github.com:ava-labs/subnet-evm into use-libe…
darioush Sep 24, 2024
7bfbe08
lint
darioush Sep 24, 2024
27a8bfb
more lint
darioush Sep 24, 2024
d72ff25
more lint
darioush Sep 24, 2024
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 accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2179,7 +2179,7 @@ func golangBindings(t *testing.T, overload bool) {
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ethereum/[email protected]", "-replace", "github.com/ethereum/go-ethereum=github.com/ava-labs/[email protected]20240912213608-cee51efc87e1")
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ethereum/[email protected]", "-replace", "github.com/ethereum/go-ethereum=github.com/ava-labs/[email protected]20240917194312-1d6987fb6342")
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
Expand Down
2 changes: 1 addition & 1 deletion accounts/abi/bind/precompilebind/precompile_bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ func TestPrecompileBind(t *testing.T) {
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ethereum/[email protected]", "-replace", "github.com/ethereum/go-ethereum=github.com/ava-labs/[email protected]20240912213608-cee51efc87e1")
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ethereum/[email protected]", "-replace", "github.com/ethereum/go-ethereum=github.com/ava-labs/[email protected]20240917194312-1d6987fb6342")
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
Expand Down
47 changes: 26 additions & 21 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
package core

import (
"bytes"
"math/big"

"github.com/ava-labs/subnet-evm/consensus"
Expand All @@ -35,8 +36,8 @@ import (
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/predicate"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/libevm"
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
)
Expand All @@ -62,30 +63,30 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
// Prior to Durango, the VM enforces the extra data is smaller than or
// equal to this size. After Durango, the VM pre-verifies the extra
// data past the dynamic fee rollup window is valid.
predicateResults, err := predicate.ParseResults(predicateBytes)
_, err := predicate.ParseResults(predicateBytes)
if err != nil {
log.Error("failed to parse predicate results creating new block context", "err", err, "extra", header.Extra)
// As mentioned above, we pre-verify the extra data to ensure this never happens.
// If we hit an error, construct a new block context rather than use a potentially half initialized value
// as defense in depth.
return newEVMBlockContext(header, chain, author, nil)
}
return newEVMBlockContext(header, chain, author, predicateResults)
return newEVMBlockContext(header, chain, author, header.Extra)
}

// NewEVMBlockContextWithPredicateResults creates a new context for use in the EVM with an override for the predicate results that is not present
// in header.Extra.
// This function is used to create a BlockContext when the header Extra data is not fully formed yet and it's more efficient to pass in predicateResults
// directly rather than re-encode the latest results when executing each individaul transaction.
func NewEVMBlockContextWithPredicateResults(header *types.Header, chain ChainContext, author *common.Address, predicateResults *predicate.Results) vm.BlockContext {
var results libevm.PredicateResults
if predicateResults != nil {
results = predicateResults
func NewEVMBlockContextWithPredicateResults(header *types.Header, chain ChainContext, author *common.Address, predicateBytes []byte) vm.BlockContext {
extra := bytes.Clone(header.Extra)
if len(predicateBytes) > 0 {
extra = predicate.SetPredicateResultBytes(extra, predicateBytes)
}
return newEVMBlockContext(header, chain, author, results)
return newEVMBlockContext(header, chain, author, extra)
}

func newEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address, predicateResults libevm.PredicateResults) vm.BlockContext {
func newEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address, extra []byte) vm.BlockContext {
var (
beneficiary common.Address
baseFee *big.Int
Expand Down Expand Up @@ -114,18 +115,22 @@ func newEVMBlockContext(header *types.Header, chain ChainContext, author *common
random.SetBytes(header.Difficulty.Bytes())
Copy link
Collaborator

Choose a reason for hiding this comment

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

isn't this potentially dangerous as we have activated Durango without this field set?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it should not be dangerous since we will not serialize this value back.
it is used by the "random" opcode, so we keep it as "difficulty", which retains the previous semantics.
This way we can avoid changing the jump table compared with upstream, which seems better.
however, I do agree that it's not in correspondence with the block header.

}
return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
GetHash: GetHashFn(header, chain),
PredicateResults: predicateResults,
Coinbase: beneficiary,
BlockNumber: new(big.Int).Set(header.Number),
Time: header.Time,
Difficulty: new(big.Int).Set(header.Difficulty),
BaseFee: baseFee,
BlobBaseFee: blobBaseFee,
GasLimit: header.GasLimit,
Random: random,
CanTransfer: CanTransfer,
Transfer: Transfer,
GetHash: GetHashFn(header, chain),
Coinbase: beneficiary,
BlockNumber: new(big.Int).Set(header.Number),
Time: header.Time,
Difficulty: new(big.Int).Set(header.Difficulty),
BaseFee: baseFee,
BlobBaseFee: blobBaseFee,
GasLimit: header.GasLimit,
Random: random,
Header: &gethtypes.Header{
Number: new(big.Int).Set(header.Number),
Time: header.Time,
Extra: extra,
},
}
}

Expand Down
12 changes: 11 additions & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"github.com/ava-labs/subnet-evm/eth/tracers/logger"
"github.com/ava-labs/subnet-evm/internal/ethapi"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/predicate"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -959,13 +960,22 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
defer release()

vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

why don't we just use NewEVMBlockContextWithPredicateResults here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure what your suggestion is here?
we still need the predicateResults below to pass into the blockContext below, so I don't think it makes a big difference


var predicateResults params.PredicateResults
predicateBytes, ok := predicate.GetPredicateResultBytes(vmctx.Header.Extra)
if ok {
predicateResults, err = predicate.ParseResults(predicateBytes)
if err != nil {
return nil, err
}
}
// Apply the customization rules if required.
if config != nil {
originalTime := block.Time()
config.BlockOverrides.Apply(&vmctx)
// Apply all relevant upgrades from [originalTime] to the block time set in the override.
// Should be applied before the state overrides.
blockContext := params.NewBlockContext(vmctx.BlockNumber, vmctx.Time, vmctx.PredicateResults)
blockContext := params.NewBlockContext(vmctx.BlockNumber, vmctx.Time, predicateResults)
err = core.ApplyUpgrades(api.backend.ChainConfig(), &originalTime, blockContext, statedb)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,6 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect
)

replace github.com/ethereum/go-ethereum => github.com/ava-labs/go-ethereum v0.0.0-20240912213608-cee51efc87e1
replace github.com/ethereum/go-ethereum => github.com/ava-labs/go-ethereum v0.0.0-20240917194312-1d6987fb6342

// replace github.com/ethereum/go-ethereum => ../go-ethereum
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ github.com/ava-labs/avalanchego v1.11.11 h1:MIQq8xRavRj4ZXHA4G+aMiymig7SOScGOG1S
github.com/ava-labs/avalanchego v1.11.11/go.mod h1:yFx3V31Jy9NFa8GZlgGnwiVf8KGjeF2+Uc99l9Scd/8=
github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732 h1:wlhGJbmb7s3bU2QWtxKjscGjfHknQiq+cVhhUjONsB8=
github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732/go.mod h1:RkQLaQ961Xe/sUb3ycn4Qi18vPPuEetTqDf2eDcquAs=
github.com/ava-labs/go-ethereum v0.0.0-20240912213608-cee51efc87e1 h1:YHFMNwxx4xdJsoIIEnSe1w5OxkKPPFoCv7uUbJ5lL7c=
github.com/ava-labs/go-ethereum v0.0.0-20240912213608-cee51efc87e1/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
github.com/ava-labs/go-ethereum v0.0.0-20240917194312-1d6987fb6342 h1:x3YR5QHayGNFyh0IA/DvUSHB2Wg6UXatJC68zEujB/Y=
github.com/ava-labs/go-ethereum v0.0.0-20240917194312-1d6987fb6342/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down
6 changes: 5 additions & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,11 @@ func (w *worker) applyTransaction(env *environment, tx *types.Transaction, coinb
}
env.predicateResults.SetTxResults(tx.Hash(), results)

blockContext = core.NewEVMBlockContextWithPredicateResults(env.header, w.chain, &coinbase, env.predicateResults)
predicateResultsBytes, err := env.predicateResults.Bytes()
if err != nil {
return nil, fmt.Errorf("failed to marshal predicate results: %w", err)
}
blockContext = core.NewEVMBlockContextWithPredicateResults(env.header, w.chain, &coinbase, predicateResultsBytes)
} else {
blockContext = core.NewEVMBlockContext(env.header, w.chain, &coinbase)
}
Expand Down
18 changes: 14 additions & 4 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,10 @@ type ChainConfigExtra struct {
UpgradeConfig `json:"-"` // Config specified in upgradeBytes (avalanche network upgrades or enable/disabling precompiles). Skip encoding/decoding directly into ChainConfig.
}

func (c ChainConfigExtra) Description() string {
func (c *ChainConfigExtra) Description() string {
if c == nil {
return ""
}
var banner string

banner += "Avalanche Upgrades (timestamp based):\n"
Expand Down Expand Up @@ -284,7 +287,10 @@ type fork struct {
optional bool // if true, the fork may be nil and next fork is still allowed
}

func (c ChainConfigExtra) CheckConfigForkOrder() error {
func (c *ChainConfigExtra) CheckConfigForkOrder() error {
if c == nil {
return nil
}
// Note: In Avalanche, hard forks must take place via block timestamps instead
// of block numbers since blocks are produced asynchronously. Therefore, we do not
// check that the block timestamps in the same way as for
Expand Down Expand Up @@ -345,7 +351,10 @@ func checkForks(forks []fork, blockFork bool) error {
return nil
}

func (c ChainConfigExtra) CheckCompatible(newcfg_ *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError {
func (c *ChainConfigExtra) CheckConfigCompatible(newcfg_ *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError {
if c == nil {
return nil
}
newcfg := GetExtra(newcfg_)

// Check avalanche network upgrades
Expand Down Expand Up @@ -427,7 +436,8 @@ func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCo
type Rules = gethparams.Rules

type RulesExtra struct {
gethrules gethparams.Rules
chainConfig *ChainConfig
gethrules gethparams.Rules

// Rules for Avalanche releases
AvalancheRules
Expand Down
12 changes: 6 additions & 6 deletions params/config_extra.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ func (c *ChainConfigExtra) UnmarshalJSON(data []byte) error {

// MarshalJSON returns the JSON encoding of c.
// This is a custom marshaler to handle the Precompiles field.
func (c ChainConfigExtra) MarshalJSON() ([]byte, error) {
func (c *ChainConfigExtra) MarshalJSON() ([]byte, error) {
// Alias ChainConfigExtra to avoid recursion
type _ChainConfigExtra ChainConfigExtra
tmp, err := json.Marshal(_ChainConfigExtra(c))
tmp, err := json.Marshal(_ChainConfigExtra(*c))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -188,7 +188,7 @@ func (cu *ChainConfigWithUpgradesJSON) UnmarshalJSON(input []byte) error {
}

// Verify verifies chain config and returns error
func (c ChainConfigExtra) Verify() error {
func (c *ChainConfigExtra) Verify() error {
if err := c.FeeConfig.Verify(); err != nil {
return err
}
Expand All @@ -212,20 +212,20 @@ func (c ChainConfigExtra) Verify() error {
}

// IsPrecompileEnabled returns whether precompile with [address] is enabled at [timestamp].
func (c ChainConfigExtra) IsPrecompileEnabled(address common.Address, timestamp uint64) bool {
func (c *ChainConfigExtra) IsPrecompileEnabled(address common.Address, timestamp uint64) bool {
config := c.getActivePrecompileConfig(address, timestamp)
return config != nil && !config.IsDisabled()
}

// GetFeeConfig returns the original FeeConfig contained in the genesis ChainConfig.
// Implements precompile.ChainConfig interface.
func (c ChainConfigExtra) GetFeeConfig() commontype.FeeConfig {
func (c *ChainConfigExtra) GetFeeConfig() commontype.FeeConfig {
return c.FeeConfig
}

// AllowedFeeRecipients returns the original AllowedFeeRecipients parameter contained in the genesis ChainConfig.
// Implements precompile.ChainConfig interface.
func (c ChainConfigExtra) AllowedFeeRecipients() bool {
func (c *ChainConfigExtra) AllowedFeeRecipients() bool {
return c.AllowFeeRecipients
}

Expand Down
17 changes: 7 additions & 10 deletions params/config_libevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,25 @@ import (
)

func do_init() any {
getter = gethparams.RegisterExtras(gethparams.Extras[ChainConfigExtra, RulesExtra]{
getter = gethparams.RegisterExtras(gethparams.Extras[*ChainConfigExtra, RulesExtra]{
ReuseJSONRoot: true, // Reuse the root JSON input when unmarshalling the extra payload.
NewRules: constructRulesExtra,
})
return nil
}

var getter gethparams.ExtraPayloadGetter[ChainConfigExtra, RulesExtra]
var getter gethparams.ExtraPayloads[*ChainConfigExtra, RulesExtra]

// constructRulesExtra acts as an adjunct to the [params.ChainConfig.Rules]
// method. Its primary purpose is to construct the extra payload for the
// [params.Rules] but it MAY also modify the [params.Rules].
func constructRulesExtra(c *gethparams.ChainConfig, r *gethparams.Rules, cEx *ChainConfigExtra, blockNum *big.Int, isMerge bool, timestamp uint64) *RulesExtra {
func constructRulesExtra(c *gethparams.ChainConfig, r *gethparams.Rules, cEx *ChainConfigExtra, blockNum *big.Int, isMerge bool, timestamp uint64) RulesExtra {
var rules RulesExtra
if cEx == nil {
return &rules
return rules
}
rules.AvalancheRules = cEx.GetAvalancheRules(timestamp)
rules.chainConfig = c
rules.gethrules = *r

// Initialize the stateful precompiles that should be enabled at [blockTimestamp].
Expand All @@ -49,7 +50,7 @@ func constructRulesExtra(c *gethparams.ChainConfig, r *gethparams.Rules, cEx *Ch
}
}

return &rules
return rules
}

// FromChainConfig returns the extra payload carried by the ChainConfig.
Expand All @@ -59,9 +60,5 @@ func FromChainConfig(c *gethparams.ChainConfig) *ChainConfigExtra {

// FromRules returns the extra payload carried by the Rules.
func FromRules(r *gethparams.Rules) RulesExtra {
extra := getter.FromRules(r)
if extra == nil {
return RulesExtra{}
}
return *extra
return getter.FromRules(r)
}
Loading
Loading