implement eip 2935 (#342)

* implement eip 2935

* add touched historical contract slot to the witness
This commit is contained in:
Guillaume Ballet 2024-01-26 17:41:31 +01:00
parent 85a7198c2d
commit ac3f26947d
6 changed files with 59 additions and 1 deletions

View file

@ -88,6 +88,7 @@ type stEnv struct {
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"`
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}
type stEnvMarshaling struct {
@ -182,6 +183,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
misc.ApplyDAOHardFork(statedb)
}
if chainConfig.IsPrague(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) {
core.ProcessParentBlockHash(statedb, pre.Env.Number-1, *pre.Env.ParentHash)
}
var blobGasUsed uint64
for i, tx := range txs {
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {

View file

@ -36,6 +36,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
@ -57,6 +58,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
enc.ParentHash = s.ParentHash
return json.Marshal(&enc)
}
@ -82,6 +84,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
@ -148,5 +151,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.ParentBlobGasUsed != nil {
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
}
if dec.ParentHash != nil {
s.ParentHash = dec.ParentHash
}
return nil
}

View file

@ -85,6 +85,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number, header.Time)
)
if p.config.IsPrague(block.Number(), block.Time()) {
ProcessParentBlockHash(statedb, block.NumberU64()-1, block.ParentHash())
}
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
@ -359,3 +362,9 @@ func (kvm *keyValueMigrator) migrateCollectedKeyValues(tree *trie.VerkleTrie) er
return nil
}
func ProcessParentBlockHash(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash) {
var key common.Hash
binary.BigEndian.PutUint64(key[24:], prevNumber)
statedb.SetState(params.HistoryStorageAddress, key, prevHash)
}

View file

@ -17,6 +17,8 @@
package vm
import (
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/state"
@ -497,6 +499,13 @@ func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
return nil, nil
}
func getBlockHashFromContract(number uint64, statedb StateDB, witness *state.AccessWitness) common.Hash {
var pnum common.Hash
binary.BigEndian.PutUint64(pnum[24:], number)
witness.TouchAddressOnReadAndComputeGas(params.HistoryStorageAddress[:], *uint256.NewInt(number / 256), byte(number&0xFF))
return statedb.GetState(params.HistoryStorageAddress, pnum)
}
func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
num := scope.Stack.peek()
num64, overflow := num.Uint64WithOverflow()
@ -504,6 +513,26 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
num.Clear()
return nil, nil
}
evm := interpreter.evm
bnum := evm.Context.BlockNumber.Uint64()
// if Prague is active, check if we are past the 256th block so that
// reading from the contract can be activated (EIP 2935).
if evm.chainRules.IsPrague && bnum > 256 {
if getBlockHashFromContract(bnum-256, evm.StateDB, evm.Accesses) != (common.Hash{}) {
// EIP-2935 case: get the block number from the fork, as we are 256 blocks
// after the fork activation.
num.SetBytes(getBlockHashFromContract(num64, evm.StateDB, evm.Accesses).Bytes())
return nil, nil
}
// if the 256th ancestor didn't have its hash stored in the
// history contract, then we are within 256 blocks of the
// fork activation, and the former behavior should be retained.
// Fall through the legacy use case.
}
var upper, lower uint64
upper = interpreter.evm.Context.BlockNumber.Uint64()
if upper < 257 {

View file

@ -920,6 +920,9 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
log.Error("Failed to create sealing context", "err", err)
return nil, err
}
if w.chainConfig.IsPrague(header.Number, header.Time) {
core.ProcessParentBlockHash(env.state, header.Number.Uint64()-1, header.ParentHash)
}
return env, nil
}

View file

@ -16,7 +16,11 @@
package params
import "math/big"
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
)
const (
GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
@ -179,4 +183,7 @@ var (
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
// HistoryStorageAddress is where the historical block hashes are stored.
HistoryStorageAddress common.Address = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
)