core/evm: RANDOM opcode (EIP-4399) (#24141)
* core: implement eip-4399 random opcode * core: make vmconfig threadsafe * core: miner: pass vmConfig by value not reference * all: enable 4399 by Rules * core: remove diff (f) * tests: set proper difficulty (f) * smaller diff (f) * eth/catalyst: nit * core: make RANDOM a pointer which is only set post-merge * cmd/evm/internal/t8ntool: fix t8n tracing of 4399 * tests: set difficulty * cmd/evm/internal/t8ntool: check that baserules are london before applying the merge chainrules
This commit is contained in:
parent
1884f37f2c
commit
b1e72f7ea9
@ -67,6 +67,7 @@ type ommer struct {
|
|||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *big.Int `json:"currentDifficulty"`
|
Difficulty *big.Int `json:"currentDifficulty"`
|
||||||
|
Random *big.Int `json:"currentRandom"`
|
||||||
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
ParentDifficulty *big.Int `json:"parentDifficulty"`
|
||||||
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number uint64 `json:"currentNumber" gencodec:"required"`
|
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||||
@ -81,6 +82,7 @@ type stEnv struct {
|
|||||||
type stEnvMarshaling struct {
|
type stEnvMarshaling struct {
|
||||||
Coinbase common.UnprefixedAddress
|
Coinbase common.UnprefixedAddress
|
||||||
Difficulty *math.HexOrDecimal256
|
Difficulty *math.HexOrDecimal256
|
||||||
|
Random *math.HexOrDecimal256
|
||||||
ParentDifficulty *math.HexOrDecimal256
|
ParentDifficulty *math.HexOrDecimal256
|
||||||
GasLimit math.HexOrDecimal64
|
GasLimit math.HexOrDecimal64
|
||||||
Number math.HexOrDecimal64
|
Number math.HexOrDecimal64
|
||||||
@ -139,6 +141,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
if pre.Env.BaseFee != nil {
|
if pre.Env.BaseFee != nil {
|
||||||
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
|
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
|
||||||
}
|
}
|
||||||
|
// If random is defined, add it to the vmContext.
|
||||||
|
if pre.Env.Random != nil {
|
||||||
|
rnd := common.BigToHash(pre.Env.Random)
|
||||||
|
vmContext.Random = &rnd
|
||||||
|
}
|
||||||
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
||||||
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
// done in StateProcessor.Process(block, ...), right before transactions are applied.
|
||||||
if chainConfig.DAOForkSupport &&
|
if chainConfig.DAOForkSupport &&
|
||||||
|
@ -18,6 +18,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
@ -31,6 +32,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||||||
var enc stEnv
|
var enc stEnv
|
||||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||||
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
||||||
|
enc.Random = (*math.HexOrDecimal256)(s.Random)
|
||||||
enc.ParentDifficulty = (*math.HexOrDecimal256)(s.ParentDifficulty)
|
enc.ParentDifficulty = (*math.HexOrDecimal256)(s.ParentDifficulty)
|
||||||
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
|
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
|
||||||
enc.Number = math.HexOrDecimal64(s.Number)
|
enc.Number = math.HexOrDecimal64(s.Number)
|
||||||
@ -48,6 +50,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
|
||||||
|
Random *math.HexOrDecimal256 `json:"currentRandom"`
|
||||||
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
@ -69,6 +72,9 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.Difficulty != nil {
|
if dec.Difficulty != nil {
|
||||||
s.Difficulty = (*big.Int)(dec.Difficulty)
|
s.Difficulty = (*big.Int)(dec.Difficulty)
|
||||||
}
|
}
|
||||||
|
if dec.Random != nil {
|
||||||
|
s.Random = (*big.Int)(dec.Random)
|
||||||
|
}
|
||||||
if dec.ParentDifficulty != nil {
|
if dec.ParentDifficulty != nil {
|
||||||
s.ParentDifficulty = (*big.Int)(dec.ParentDifficulty)
|
s.ParentDifficulty = (*big.Int)(dec.ParentDifficulty)
|
||||||
}
|
}
|
||||||
|
@ -252,6 +252,10 @@ func Transition(ctx *cli.Context) error {
|
|||||||
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Sanity check, to not `panic` in state_transition
|
||||||
|
if prestate.Env.Random != nil && !chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
||||||
|
return NewError(ErrorConfig, errors.New("can only apply RANDOM on top of London chainrules"))
|
||||||
|
}
|
||||||
if env := prestate.Env; env.Difficulty == nil {
|
if env := prestate.Env; env.Difficulty == nil {
|
||||||
// If difficulty was not provided by caller, we need to calculate it.
|
// If difficulty was not provided by caller, we need to calculate it.
|
||||||
switch {
|
switch {
|
||||||
|
@ -43,7 +43,6 @@ var (
|
|||||||
// error types into the consensus package.
|
// error types into the consensus package.
|
||||||
var (
|
var (
|
||||||
errTooManyUncles = errors.New("too many uncles")
|
errTooManyUncles = errors.New("too many uncles")
|
||||||
errInvalidMixDigest = errors.New("invalid mix digest")
|
|
||||||
errInvalidNonce = errors.New("invalid nonce")
|
errInvalidNonce = errors.New("invalid nonce")
|
||||||
errInvalidUncleHash = errors.New("invalid uncle hash")
|
errInvalidUncleHash = errors.New("invalid uncle hash")
|
||||||
)
|
)
|
||||||
@ -182,10 +181,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
|||||||
if len(header.Extra) > 32 {
|
if len(header.Extra) > 32 {
|
||||||
return fmt.Errorf("extra-data longer than 32 bytes (%d)", len(header.Extra))
|
return fmt.Errorf("extra-data longer than 32 bytes (%d)", len(header.Extra))
|
||||||
}
|
}
|
||||||
// Verify the seal parts. Ensure the mixhash, nonce and uncle hash are the expected value.
|
// Verify the seal parts. Ensure the nonce and uncle hash are the expected value.
|
||||||
if header.MixDigest != (common.Hash{}) {
|
|
||||||
return errInvalidMixDigest
|
|
||||||
}
|
|
||||||
if header.Nonce != beaconNonce {
|
if header.Nonce != beaconNonce {
|
||||||
return errInvalidNonce
|
return errInvalidNonce
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
var (
|
var (
|
||||||
beneficiary common.Address
|
beneficiary common.Address
|
||||||
baseFee *big.Int
|
baseFee *big.Int
|
||||||
|
random *common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
// If we don't have an explicit author (i.e. not mining), extract from the header
|
// If we don't have an explicit author (i.e. not mining), extract from the header
|
||||||
@ -51,6 +52,9 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
if header.BaseFee != nil {
|
if header.BaseFee != nil {
|
||||||
baseFee = new(big.Int).Set(header.BaseFee)
|
baseFee = new(big.Int).Set(header.BaseFee)
|
||||||
}
|
}
|
||||||
|
if header.Difficulty.Cmp(common.Big0) == 0 {
|
||||||
|
random = &header.MixDigest
|
||||||
|
}
|
||||||
return vm.BlockContext{
|
return vm.BlockContext{
|
||||||
CanTransfer: CanTransfer,
|
CanTransfer: CanTransfer,
|
||||||
Transfer: Transfer,
|
Transfer: Transfer,
|
||||||
@ -61,6 +65,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
Difficulty: new(big.Int).Set(header.Difficulty),
|
Difficulty: new(big.Int).Set(header.Difficulty),
|
||||||
BaseFee: baseFee,
|
BaseFee: baseFee,
|
||||||
GasLimit: header.GasLimit,
|
GasLimit: header.GasLimit,
|
||||||
|
Random: random,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
|||||||
if g.GasLimit == 0 {
|
if g.GasLimit == 0 {
|
||||||
head.GasLimit = params.GenesisGasLimit
|
head.GasLimit = params.GenesisGasLimit
|
||||||
}
|
}
|
||||||
if g.Difficulty == nil {
|
if g.Difficulty == nil && g.Mixhash == (common.Hash{}) {
|
||||||
head.Difficulty = params.GenesisDifficulty
|
head.Difficulty = params.GenesisDifficulty
|
||||||
}
|
}
|
||||||
if g.Config != nil && g.Config.IsLondon(common.Big0) {
|
if g.Config != nil && g.Config.IsLondon(common.Big0) {
|
||||||
|
@ -310,7 +310,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up the initial access list.
|
// Set up the initial access list.
|
||||||
if rules := st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber); rules.IsBerlin {
|
if rules := st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil); rules.IsBerlin {
|
||||||
st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
|
st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
@ -75,6 +75,7 @@ type BlockContext struct {
|
|||||||
Time *big.Int // Provides information for TIME
|
Time *big.Int // Provides information for TIME
|
||||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||||
BaseFee *big.Int // Provides information for BASEFEE
|
BaseFee *big.Int // Provides information for BASEFEE
|
||||||
|
Random *common.Hash // Provides information for RANDOM
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxContext provides the EVM with information about a transaction.
|
// TxContext provides the EVM with information about a transaction.
|
||||||
@ -131,7 +132,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
|
|||||||
StateDB: statedb,
|
StateDB: statedb,
|
||||||
Config: config,
|
Config: config,
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil),
|
||||||
}
|
}
|
||||||
evm.interpreter = NewEVMInterpreter(evm, config)
|
evm.interpreter = NewEVMInterpreter(evm, config)
|
||||||
return evm
|
return evm
|
||||||
|
@ -477,6 +477,12 @@ func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
v := new(uint256.Int).SetBytes((interpreter.evm.Context.Random.Bytes()))
|
||||||
|
scope.Stack.push(v)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
|
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -654,3 +655,36 @@ func TestCreate2Addreses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRandom(t *testing.T) {
|
||||||
|
type testcase struct {
|
||||||
|
name string
|
||||||
|
random common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range []testcase{
|
||||||
|
{name: "empty hash", random: common.Hash{}},
|
||||||
|
{name: "1", random: common.Hash{0}},
|
||||||
|
{name: "emptyCodeHash", random: emptyCodeHash},
|
||||||
|
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
|
||||||
|
} {
|
||||||
|
var (
|
||||||
|
env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{})
|
||||||
|
stack = newstack()
|
||||||
|
pc = uint64(0)
|
||||||
|
evmInterpreter = env.interpreter
|
||||||
|
)
|
||||||
|
opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
||||||
|
if len(stack.data) != 1 {
|
||||||
|
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||||
|
}
|
||||||
|
actual := stack.pop()
|
||||||
|
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes()))
|
||||||
|
if overflow {
|
||||||
|
t.Errorf("Testcase %v: invalid overflow", tt.name)
|
||||||
|
}
|
||||||
|
if actual.Cmp(expected) != 0 {
|
||||||
|
t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -69,6 +69,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
|||||||
// If jump table was not initialised we set the default one.
|
// If jump table was not initialised we set the default one.
|
||||||
if cfg.JumpTable == nil {
|
if cfg.JumpTable == nil {
|
||||||
switch {
|
switch {
|
||||||
|
case evm.chainRules.IsMerge:
|
||||||
|
cfg.JumpTable = &mergeInstructionSet
|
||||||
case evm.chainRules.IsLondon:
|
case evm.chainRules.IsLondon:
|
||||||
cfg.JumpTable = &londonInstructionSet
|
cfg.JumpTable = &londonInstructionSet
|
||||||
case evm.chainRules.IsBerlin:
|
case evm.chainRules.IsBerlin:
|
||||||
|
@ -54,6 +54,7 @@ var (
|
|||||||
istanbulInstructionSet = newIstanbulInstructionSet()
|
istanbulInstructionSet = newIstanbulInstructionSet()
|
||||||
berlinInstructionSet = newBerlinInstructionSet()
|
berlinInstructionSet = newBerlinInstructionSet()
|
||||||
londonInstructionSet = newLondonInstructionSet()
|
londonInstructionSet = newLondonInstructionSet()
|
||||||
|
mergeInstructionSet = newMergeInstructionSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||||
@ -77,6 +78,17 @@ func validate(jt JumpTable) JumpTable {
|
|||||||
return jt
|
return jt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newMergeInstructionSet() JumpTable {
|
||||||
|
instructionSet := newLondonInstructionSet()
|
||||||
|
instructionSet[RANDOM] = &operation{
|
||||||
|
execute: opRandom,
|
||||||
|
constantGas: GasQuickStep,
|
||||||
|
minStack: minStack(0, 1),
|
||||||
|
maxStack: maxStack(0, 1),
|
||||||
|
}
|
||||||
|
return validate(instructionSet)
|
||||||
|
}
|
||||||
|
|
||||||
// newLondonInstructionSet returns the frontier, homestead, byzantium,
|
// newLondonInstructionSet returns the frontier, homestead, byzantium,
|
||||||
// contantinople, istanbul, petersburg, berlin and london instructions.
|
// contantinople, istanbul, petersburg, berlin and london instructions.
|
||||||
func newLondonInstructionSet() JumpTable {
|
func newLondonInstructionSet() JumpTable {
|
||||||
|
@ -95,6 +95,7 @@ const (
|
|||||||
TIMESTAMP OpCode = 0x42
|
TIMESTAMP OpCode = 0x42
|
||||||
NUMBER OpCode = 0x43
|
NUMBER OpCode = 0x43
|
||||||
DIFFICULTY OpCode = 0x44
|
DIFFICULTY OpCode = 0x44
|
||||||
|
RANDOM OpCode = 0x44 // Same as DIFFICULTY
|
||||||
GASLIMIT OpCode = 0x45
|
GASLIMIT OpCode = 0x45
|
||||||
CHAINID OpCode = 0x46
|
CHAINID OpCode = 0x46
|
||||||
SELFBALANCE OpCode = 0x47
|
SELFBALANCE OpCode = 0x47
|
||||||
@ -275,7 +276,7 @@ var opCodeToString = map[OpCode]string{
|
|||||||
COINBASE: "COINBASE",
|
COINBASE: "COINBASE",
|
||||||
TIMESTAMP: "TIMESTAMP",
|
TIMESTAMP: "TIMESTAMP",
|
||||||
NUMBER: "NUMBER",
|
NUMBER: "NUMBER",
|
||||||
DIFFICULTY: "DIFFICULTY",
|
DIFFICULTY: "DIFFICULTY", // TODO (MariusVanDerWijden) rename to RANDOM post merge
|
||||||
GASLIMIT: "GASLIMIT",
|
GASLIMIT: "GASLIMIT",
|
||||||
CHAINID: "CHAINID",
|
CHAINID: "CHAINID",
|
||||||
SELFBALANCE: "SELFBALANCE",
|
SELFBALANCE: "SELFBALANCE",
|
||||||
|
@ -118,7 +118,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
|||||||
vmenv = NewEnv(cfg)
|
vmenv = NewEnv(cfg)
|
||||||
sender = vm.AccountRef(cfg.Origin)
|
sender = vm.AccountRef(cfg.Origin)
|
||||||
)
|
)
|
||||||
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber); rules.IsBerlin {
|
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil); rules.IsBerlin {
|
||||||
cfg.State.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
|
cfg.State.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
|
||||||
}
|
}
|
||||||
cfg.State.CreateAccount(address)
|
cfg.State.CreateAccount(address)
|
||||||
@ -150,7 +150,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
|||||||
vmenv = NewEnv(cfg)
|
vmenv = NewEnv(cfg)
|
||||||
sender = vm.AccountRef(cfg.Origin)
|
sender = vm.AccountRef(cfg.Origin)
|
||||||
)
|
)
|
||||||
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber); rules.IsBerlin {
|
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil); rules.IsBerlin {
|
||||||
cfg.State.PrepareAccessList(cfg.Origin, nil, vm.ActivePrecompiles(rules), nil)
|
cfg.State.PrepareAccessList(cfg.Origin, nil, vm.ActivePrecompiles(rules), nil)
|
||||||
}
|
}
|
||||||
// Call the code with the given configuration.
|
// Call the code with the given configuration.
|
||||||
@ -176,7 +176,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
|
|||||||
sender := cfg.State.GetOrNewStateObject(cfg.Origin)
|
sender := cfg.State.GetOrNewStateObject(cfg.Origin)
|
||||||
statedb := cfg.State
|
statedb := cfg.State
|
||||||
|
|
||||||
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber); rules.IsBerlin {
|
if rules := cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil); rules.IsBerlin {
|
||||||
statedb.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
|
statedb.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
|
||||||
}
|
}
|
||||||
// Call the code with the given configuration.
|
// Call the code with the given configuration.
|
||||||
|
@ -133,9 +133,9 @@ type blockExecutionEnv struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (env *blockExecutionEnv) commitTransaction(tx *types.Transaction, coinbase common.Address) error {
|
func (env *blockExecutionEnv) commitTransaction(tx *types.Transaction, coinbase common.Address) error {
|
||||||
vmconfig := *env.chain.GetVMConfig()
|
vmConfig := *env.chain.GetVMConfig()
|
||||||
snap := env.state.Snapshot()
|
snap := env.state.Snapshot()
|
||||||
receipt, err := core.ApplyTransaction(env.chain.Config(), env.chain, &coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, vmconfig)
|
receipt, err := core.ApplyTransaction(env.chain.Config(), env.chain, &coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, vmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.state.RevertToSnapshot(snap)
|
env.state.RevertToSnapshot(snap)
|
||||||
return err
|
return err
|
||||||
@ -318,6 +318,7 @@ func (api *ConsensusAPI) assembleBlock(parentHash common.Hash, params *PayloadAt
|
|||||||
GasLimit: parent.GasLimit(), // Keep the gas limit constant in this prototype
|
GasLimit: parent.GasLimit(), // Keep the gas limit constant in this prototype
|
||||||
Extra: []byte{}, // TODO (MariusVanDerWijden) properly set extra data
|
Extra: []byte{}, // TODO (MariusVanDerWijden) properly set extra data
|
||||||
Time: params.Timestamp,
|
Time: params.Timestamp,
|
||||||
|
MixDigest: params.Random,
|
||||||
}
|
}
|
||||||
if config := api.eth.BlockChain().Config(); config.IsLondon(header.Number) {
|
if config := api.eth.BlockChain().Config(); config.IsLondon(header.Number) {
|
||||||
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
|
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
|
||||||
@ -432,7 +433,7 @@ func ExecutableDataToBlock(params ExecutableDataV1) (*types.Block, error) {
|
|||||||
Time: params.Timestamp,
|
Time: params.Timestamp,
|
||||||
BaseFee: params.BaseFeePerGas,
|
BaseFee: params.BaseFeePerGas,
|
||||||
Extra: params.ExtraData,
|
Extra: params.ExtraData,
|
||||||
// TODO (MariusVanDerWijden) add params.Random to header once required
|
MixDigest: params.Random,
|
||||||
}
|
}
|
||||||
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
|
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
|
||||||
if block.Hash() != params.BlockHash {
|
if block.Hash() != params.BlockHash {
|
||||||
|
@ -697,7 +697,7 @@ func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
|
|||||||
jst.ctx["block"] = env.Context.BlockNumber.Uint64()
|
jst.ctx["block"] = env.Context.BlockNumber.Uint64()
|
||||||
jst.dbWrapper.db = env.StateDB
|
jst.dbWrapper.db = env.StateDB
|
||||||
// Update list of precompiles based on current block
|
// Update list of precompiles based on current block
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber)
|
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
|
||||||
jst.activePrecompiles = vm.ActivePrecompiles(rules)
|
jst.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
|
|
||||||
// Compute intrinsic gas
|
// Compute intrinsic gas
|
||||||
|
@ -83,7 +83,7 @@ func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
|
|||||||
t.env = env
|
t.env = env
|
||||||
|
|
||||||
// Update list of precompiles based on current block
|
// Update list of precompiles based on current block
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber)
|
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
|
|
||||||
// Save the outer calldata also
|
// Save the outer calldata also
|
||||||
|
@ -1432,8 +1432,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||||||
} else {
|
} else {
|
||||||
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
|
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
|
||||||
}
|
}
|
||||||
|
isPostMerge := header.Difficulty.Cmp(common.Big0) == 0
|
||||||
// Retrieve the precompiles since they don't need to be added to the access list
|
// Retrieve the precompiles since they don't need to be added to the access list
|
||||||
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number))
|
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge))
|
||||||
|
|
||||||
// Create an initial tracer
|
// Create an initial tracer
|
||||||
prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)
|
prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)
|
||||||
|
@ -267,7 +267,7 @@ var (
|
|||||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
|
||||||
|
|
||||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int), false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
|
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
|
||||||
@ -668,10 +668,11 @@ type Rules struct {
|
|||||||
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
||||||
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
||||||
IsBerlin, IsLondon bool
|
IsBerlin, IsLondon bool
|
||||||
|
IsMerge bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rules ensures c's ChainID is not nil.
|
// Rules ensures c's ChainID is not nil.
|
||||||
func (c *ChainConfig) Rules(num *big.Int) Rules {
|
func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules {
|
||||||
chainID := c.ChainID
|
chainID := c.ChainID
|
||||||
if chainID == nil {
|
if chainID == nil {
|
||||||
chainID = new(big.Int)
|
chainID = new(big.Int)
|
||||||
@ -688,5 +689,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
|
|||||||
IsIstanbul: c.IsIstanbul(num),
|
IsIstanbul: c.IsIstanbul(num),
|
||||||
IsBerlin: c.IsBerlin(num),
|
IsBerlin: c.IsBerlin(num),
|
||||||
IsLondon: c.IsLondon(num),
|
IsLondon: c.IsLondon(num),
|
||||||
|
IsMerge: isMerge,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@ var _ = (*stEnvMarshaling)(nil)
|
|||||||
func (s stEnv) MarshalJSON() ([]byte, error) {
|
func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
|
||||||
|
Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
@ -26,6 +27,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||||||
var enc stEnv
|
var enc stEnv
|
||||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||||
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
||||||
|
enc.Random = (*math.HexOrDecimal256)(s.Random)
|
||||||
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
|
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
|
||||||
enc.Number = math.HexOrDecimal64(s.Number)
|
enc.Number = math.HexOrDecimal64(s.Number)
|
||||||
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
|
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
|
||||||
@ -37,7 +39,8 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||||||
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
|
||||||
|
Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
@ -51,10 +54,12 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||||||
return errors.New("missing required field 'currentCoinbase' for stEnv")
|
return errors.New("missing required field 'currentCoinbase' for stEnv")
|
||||||
}
|
}
|
||||||
s.Coinbase = common.Address(*dec.Coinbase)
|
s.Coinbase = common.Address(*dec.Coinbase)
|
||||||
if dec.Difficulty == nil {
|
if dec.Difficulty != nil {
|
||||||
return errors.New("missing required field 'currentDifficulty' for stEnv")
|
s.Difficulty = (*big.Int)(dec.Difficulty)
|
||||||
|
}
|
||||||
|
if dec.Random != nil {
|
||||||
|
s.Random = (*big.Int)(dec.Random)
|
||||||
}
|
}
|
||||||
s.Difficulty = (*big.Int)(dec.Difficulty)
|
|
||||||
if dec.GasLimit == nil {
|
if dec.GasLimit == nil {
|
||||||
return errors.New("missing required field 'currentGasLimit' for stEnv")
|
return errors.New("missing required field 'currentGasLimit' for stEnv")
|
||||||
}
|
}
|
||||||
|
@ -80,16 +80,18 @@ type stPostState struct {
|
|||||||
|
|
||||||
type stEnv struct {
|
type stEnv struct {
|
||||||
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
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"`
|
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
||||||
Number uint64 `json:"currentNumber" gencodec:"required"`
|
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||||
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
||||||
BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
|
BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type stEnvMarshaling struct {
|
type stEnvMarshaling struct {
|
||||||
Coinbase common.UnprefixedAddress
|
Coinbase common.UnprefixedAddress
|
||||||
Difficulty *math.HexOrDecimal256
|
Difficulty *math.HexOrDecimal256
|
||||||
|
Random *math.HexOrDecimal256
|
||||||
GasLimit math.HexOrDecimal64
|
GasLimit math.HexOrDecimal64
|
||||||
Number math.HexOrDecimal64
|
Number math.HexOrDecimal64
|
||||||
Timestamp math.HexOrDecimal64
|
Timestamp math.HexOrDecimal64
|
||||||
@ -218,8 +220,12 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||||
context.GetHash = vmTestBlockHash
|
context.GetHash = vmTestBlockHash
|
||||||
context.BaseFee = baseFee
|
context.BaseFee = baseFee
|
||||||
|
if t.json.Env.Random != nil {
|
||||||
|
rnd := common.BigToHash(t.json.Env.Random)
|
||||||
|
context.Random = &rnd
|
||||||
|
context.Difficulty = big.NewInt(0)
|
||||||
|
}
|
||||||
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||||
|
|
||||||
// Execute the message.
|
// Execute the message.
|
||||||
snapshot := statedb.Snapshot()
|
snapshot := statedb.Snapshot()
|
||||||
gaspool := new(core.GasPool)
|
gaspool := new(core.GasPool)
|
||||||
@ -268,7 +274,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||||
return &core.Genesis{
|
genesis := &core.Genesis{
|
||||||
Config: config,
|
Config: config,
|
||||||
Coinbase: t.json.Env.Coinbase,
|
Coinbase: t.json.Env.Coinbase,
|
||||||
Difficulty: t.json.Env.Difficulty,
|
Difficulty: t.json.Env.Difficulty,
|
||||||
@ -277,6 +283,12 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
|||||||
Timestamp: t.json.Env.Timestamp,
|
Timestamp: t.json.Env.Timestamp,
|
||||||
Alloc: t.json.Pre,
|
Alloc: t.json.Pre,
|
||||||
}
|
}
|
||||||
|
if t.json.Env.Random != nil {
|
||||||
|
// Post-Merge
|
||||||
|
genesis.Mixhash = common.BigToHash(t.json.Env.Random)
|
||||||
|
genesis.Difficulty = big.NewInt(0)
|
||||||
|
}
|
||||||
|
return genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) {
|
func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user