Skip to content

Commit

Permalink
implement eip 2935 (#342)
Browse files Browse the repository at this point in the history
* implement eip 2935

* add touched historical contract slot to the witness
  • Loading branch information
gballet authored Jan 26, 2024
1 parent 884b57c commit 10e3065
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 1 deletion.
4 changes: 4 additions & 0 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions cmd/evm/internal/t8ntool/gen_stenv.go

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

9 changes: 9 additions & 0 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
29 changes: 29 additions & 0 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -497,13 +499,40 @@ 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()
if overflow {
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 {
Expand Down
3 changes: 3 additions & 0 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
9 changes: 8 additions & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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")
)

0 comments on commit 10e3065

Please sign in to comment.