Skip to content

Commit

Permalink
populate vm.BlockContext.Random as Difficulty starting at Durango (to…
Browse files Browse the repository at this point in the history
… be like Merge)
  • Loading branch information
darioush committed Sep 13, 2024
1 parent 34a17a6 commit 73b5559
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 35 deletions.
9 changes: 4 additions & 5 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if pre.Env.BaseFee != nil {
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
}
// NOTE: this has been removed
// If random is defined, add it to the vmContext.
// if pre.Env.Random != nil {
// rnd := common.BigToHash(pre.Env.Random)
// vmContext.Random = &rnd
// }
if pre.Env.Random != nil {
rnd := common.BigToHash(pre.Env.Random)
vmContext.Random = &rnd
}
// Calculate the BlobBaseFee
var excessBlobGas uint64
if pre.Env.ExcessBlobGas != nil {
Expand Down
4 changes: 2 additions & 2 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
// instruction will panic during execution if it attempts to access a block number outside
// of the range created by GenerateChain.
func (b *BlockGen) AddTx(tx *types.Transaction) {
b.addTx(nil, vm.Config{}, tx)
b.addTx(&BlockChain{chainConfig: params.TestChainConfig}, vm.Config{}, tx)
}

// AddTxWithChain adds a transaction to the generated block. If no coinbase has
Expand All @@ -166,7 +166,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
// been set, the block's coinbase is set to the zero address.
// The evm interpreter can be customized with the provided vm config.
func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) {
b.addTx(nil, config, tx)
b.addTx(&BlockChain{chainConfig: params.TestChainConfig}, config, tx)
}

// GetBalance returns the balance of the given address at the generated block.
Expand Down
18 changes: 16 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ import (
"github.com/ava-labs/subnet-evm/consensus"
"github.com/ava-labs/subnet-evm/consensus/misc/eip4844"
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/predicate"
"github.com/ethereum/go-ethereum/common"
"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 @@ -47,6 +49,8 @@ type ChainContext interface {

// GetHeader returns the header corresponding to the hash/number argument pair.
GetHeader(common.Hash, uint64) *types.Header

Config() *params.ChainConfig
}

// NewEVMBlockContext creates a new context for use in the EVM.
Expand All @@ -73,15 +77,16 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
// 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 {
func NewEVMBlockContextWithPredicateResults(header *types.Header, chain ChainContext, author *common.Address, predicateResults libevm.PredicateResults) vm.BlockContext {
return newEVMBlockContext(header, chain, author, predicateResults)
}

func newEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address, predicateResults *predicate.Results) vm.BlockContext {
func newEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address, predicateResults libevm.PredicateResults) vm.BlockContext {
var (
beneficiary common.Address
baseFee *big.Int
blobBaseFee *big.Int
random *common.Hash
)

// If we don't have an explicit author (i.e. not mining), extract from the header
Expand All @@ -96,6 +101,14 @@ func newEVMBlockContext(header *types.Header, chain ChainContext, author *common
if header.ExcessBlobGas != nil {
blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
}

// Durango enables the Shanghai upgrade of eth, which takes place after the
// Merge upgrade.
isDurango := params.GetExtra(chain.Config()).IsDurango(header.Time)
if isDurango {
random = new(common.Hash)
random.SetBytes(header.Difficulty.Bytes())
}
return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
Expand All @@ -108,6 +121,7 @@ func newEVMBlockContext(header *types.Header, chain ChainContext, author *common
BaseFee: baseFee,
BlobBaseFee: blobBaseFee,
GasLimit: header.GasLimit,
Random: random,
}
}

Expand Down
1 change: 1 addition & 0 deletions core/vm/runtime/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func NewEnv(cfg *Config) *vm.EVM {
GasLimit: cfg.GasLimit,
BaseFee: cfg.BaseFee,
BlobBaseFee: cfg.BlobBaseFee,
Random: cfg.Random,
}

return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
Expand Down
2 changes: 2 additions & 0 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ func (d *dummyChain) GetHeader(h common.Hash, n uint64) *types.Header {
return fakeHeader(n, parentHash)
}

func (d *dummyChain) Config() *params.ChainConfig { return params.TestChainConfig }

// TestBlockhash tests the blockhash operation. It's a bit special, since it internally
// requires access to a chain reader.
func TestBlockhash(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,7 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
type ChainContextBackend interface {
Engine() consensus.Engine
HeaderByNumber(context.Context, rpc.BlockNumber) (*types.Header, error)
ChainConfig() *params.ChainConfig
}

// ChainContext is an implementation of core.ChainContext. It's main use-case
Expand All @@ -1050,6 +1051,10 @@ func NewChainContext(ctx context.Context, backend ChainContextBackend) *ChainCon
return &ChainContext{ctx: ctx, b: backend}
}

func (context *ChainContext) Config() *params.ChainConfig {
return context.b.ChainConfig()
}

func (context *ChainContext) Engine() consensus.Engine {
return context.b.Engine()
}
Expand Down
7 changes: 6 additions & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/libevm"
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
)
Expand Down Expand Up @@ -352,7 +353,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)
var predicateResults libevm.PredicateResults
if env.predicateResults != nil {
predicateResults = env.predicateResults
}
blockContext = core.NewEVMBlockContextWithPredicateResults(env.header, w.chain, &coinbase, predicateResults)
} else {
blockContext = core.NewEVMBlockContext(env.header, w.chain, &coinbase)
}
Expand Down
6 changes: 0 additions & 6 deletions params/config_libevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ func constructRulesExtra(c *gethparams.ChainConfig, r *gethparams.Rules, cEx *Ch
return &rules
}
rules.AvalancheRules = cEx.GetAvalancheRules(timestamp)
if rules.AvalancheRules.IsDurango || rules.AvalancheRules.IsEtna {
// After Durango, geth rules should be used with isMerge set to true.
// We can't call c.Rules because it will recurse back here.
r.IsShanghai = c.IsShanghai(blockNum, timestamp)
r.IsCancun = c.IsCancun(blockNum, timestamp)
}
rules.gethrules = *r

// Initialize the stateful precompiles that should be enabled at [blockTimestamp].
Expand Down
11 changes: 2 additions & 9 deletions params/hooks_libevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,13 @@ import (
"github.com/ava-labs/subnet-evm/precompile/precompileconfig"
"github.com/ava-labs/subnet-evm/vmerrs"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/libevm"
gethparams "github.com/ethereum/go-ethereum/params"
)

func (r RulesExtra) JumpTable() interface{} {
switch {
case r.gethrules.IsCancun:
return &vm.SubnetEVMCancunInstructionSet
case r.IsDurango:
return &vm.SubnetEVMDurangoInstructionSet
case r.IsSubnetEVM:
return &vm.SubnetEVMInstructionSet
}
// XXX: This does not account for the any possible differences in EIP-3529
// Do not merge without verifying.
return nil
}

Expand Down
13 changes: 6 additions & 7 deletions tests/gen_stenv.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ var Forks = map[string]*params.ChainConfig{
IstanbulBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ShanghaiTime: utils.NewUint64(0),
CancunTime: utils.NewUint64(0),
},
&params.ChainConfigExtra{
Expand Down
10 changes: 7 additions & 3 deletions tests/state_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type stPostState struct {
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
Random *big.Int `json:"currentRandom" gencodec:"optional"`
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
Number uint64 `json:"currentNumber" gencodec:"required"`
Expand Down Expand Up @@ -300,10 +300,14 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh

// Prepare the EVM.
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
chainCtx := &withChainConfig{nil, config}
context := core.NewEVMBlockContext(block.Header(), chainCtx, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
if params.GetExtra(config).IsSubnetEVM(0) && t.json.Env.Random != nil {
context.Random = nil
if config.IsLondon(new(big.Int)) && t.json.Env.Random != nil {
rnd := common.BigToHash(t.json.Env.Random)
context.Random = &rnd
context.Difficulty = big.NewInt(0)
}
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
Expand Down
41 changes: 41 additions & 0 deletions tests/state_test_util_ext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// (c) 2024, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package tests

import (
"github.com/ava-labs/subnet-evm/core"
"github.com/ava-labs/subnet-evm/params"
)

type withChainConfig struct {
core.ChainContext
config *params.ChainConfig
}

func (w withChainConfig) Config() *params.ChainConfig {
return w.config
}

0 comments on commit 73b5559

Please sign in to comment.