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

Update EIP-2935 for Prague devnet1 #12162

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 0 additions & 14 deletions consensus/misc/eip2935.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,6 @@ func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState,
return
}
storeHash(headerNum-1, header.ParentHash, state)
// If this is the fork block, add the parent's direct `HISTORY_SERVE_WINDOW - 1` ancestors as well
parent := headerReader.GetHeader(header.ParentHash, headerNum-1)
if parent.Time < config.PragueTime.Uint64() {
p := headerNum - 1
window := params.BlockHashHistoryServeWindow - 1
if p < window {
window = p
}
for i := window; i > 0; i-- {
p = p - 1
storeHash(p, parent.ParentHash, state)
parent = headerReader.GetHeader(parent.ParentHash, p)
}
}
}

func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) {
Expand Down
6 changes: 0 additions & 6 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ var activators = map[int]func(*JumpTable){
3855: enable3855,
3529: enable3529,
3198: enable3198,
2935: enable2935,
2929: enable2929,
2200: enable2200,
1884: enable1884,
Expand Down Expand Up @@ -322,8 +321,3 @@ func enable7516(jt *JumpTable) {
numPush: 1,
}
}

// enable2935 applies EIP-2935 (Historical block hashes in state)
func enable2935(jt *JumpTable) {
jt[BLOCKHASH].execute = opBlockhash2935
}
33 changes: 1 addition & 32 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
return nil, nil
}

// opBlockhash executes the BLOCKHASH opcode pre-EIP-2935
// opBlockhash executes the BLOCKHASH opcode
func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
arg := scope.Stack.Peek()
arg64, overflow := arg.Uint64WithOverflow()
Expand All @@ -487,37 +487,6 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
return nil, nil
}

// opBlockhash2935 executes for the BLOCKHASH opcode post EIP-2935 by returning the
// corresponding hash for the blocknumber from the state, if within range.
// The range is defined by [head - params.BlockHashHistoryServeWindow - 1, head - 1]
// This should not be used without activating EIP-2935
func opBlockhash2935(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
arg := scope.Stack.Peek()
arg64, overflow := arg.Uint64WithOverflow()
if overflow {
arg.Clear()
return nil, nil
}

// Check if arg is within allowed window
var upper uint64
upper = interpreter.evm.Context.BlockNumber
if arg64 >= upper || arg64+params.BlockHashHistoryServeWindow < upper {
arg.Clear()
return nil, nil
}

// Return state read value from the slot
storageSlot := libcommon.BytesToHash(uint256.NewInt(arg64 % params.BlockHashHistoryServeWindow).Bytes())
interpreter.evm.intraBlockState.GetState(
params.HistoryStorageAddress,
&storageSlot,
arg,
)

return nil, nil
}

func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
return nil, nil
Expand Down
1 change: 0 additions & 1 deletion core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ func validateAndFillMaxStack(jt *JumpTable) {
// cancun, and prague instructions.
func newPragueInstructionSet() JumpTable {
instructionSet := newCancunInstructionSet()
enable2935(&instructionSet)
validateAndFillMaxStack(&instructionSet)
return instructionSet
}
Expand Down
70 changes: 1 addition & 69 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,16 @@ import (
"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/kv/memdb"

"github.com/ledgerwatch/erigon/accounts/abi"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/consensus"
"github.com/ledgerwatch/erigon/consensus/misc"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/asm"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/eth/tracers/logger"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/rlp"
)

Expand Down Expand Up @@ -387,73 +386,6 @@ func TestBlockhash(t *testing.T) {
}
}

func TestBlockHashEip2935(t *testing.T) {
t.Parallel()

// This is the contract we're using. It requests the blockhash for current num (should be all zeroes), We are fetching BlockHash for current block (should be zer0), parent block, last block which is supposed to be there (head - HISTORY_SERVE_WINDOW) and also one block before that (should be zero)

/*
pragma solidity ^0.8.25;
contract BlockHashTestPrague{
function test() public view returns (bytes32, bytes32, bytes32, bytes32){
uint256 head = block.number;
bytes32 zero = blockhash(head);
bytes32 first = blockhash(head-1);
bytes32 last = blockhash(head - 8192);
bytes32 beyond = blockhash(head - 8193);
return (zero, first, last, beyond);
}
}
*/
// The contract above
data := libcommon.Hex2Bytes("608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063f8a8fd6d1461002d575b5f80fd5b61003561004e565b60405161004594939291906100bf565b60405180910390f35b5f805f805f4390505f814090505f6001836100699190610138565b4090505f6120008461007b9190610138565b4090505f6120018561008d9190610138565b409050838383839850985098509850505050505090919293565b5f819050919050565b6100b9816100a7565b82525050565b5f6080820190506100d25f8301876100b0565b6100df60208301866100b0565b6100ec60408301856100b0565b6100f960608301846100b0565b95945050505050565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61014282610102565b915061014d83610102565b92508282039050818111156101655761016461010b565b5b9291505056fea2646970667358221220bac67d00c05154c1dca13fe3c1493172d44692d312cb3fd72a3d7457874d595464736f6c63430008190033")
// The method call to 'test()'
input := libcommon.Hex2Bytes("f8a8fd6d")

// Current head
n := uint64(10000)
parentHash := libcommon.Hash{}
s := common.LeftPadBytes(big.NewInt(int64(n-1)).Bytes(), 32)
copy(parentHash[:], s)
fakeHeaderReader := &FakeChainHeaderReader{}
header := fakeHeaderReader.GetHeader(libcommon.BigToHash(big.NewInt(int64(n))), n)

chain := &dummyChain{}
cfg := &Config{
GetHashFn: core.GetHashFn(header, chain.GetHeader),
BlockNumber: new(big.Int).Set(header.Number),
Time: big.NewInt(10000),
}
setDefaults(cfg)
cfg.ChainConfig.PragueTime = big.NewInt(10000)
_, tx := memdb.NewTestTx(t)
cfg.State = state.New(state.NewPlainStateReader(tx))
cfg.State.CreateAccount(params.HistoryStorageAddress, true)
misc.StoreBlockHashesEip2935(header, cfg.State, cfg.ChainConfig, &FakeChainHeaderReader{})

ret, _, err := Execute(data, input, cfg, header.Number.Uint64())
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if len(ret) != 128 {
t.Fatalf("expected returndata to be 128 bytes, got %d", len(ret))
}

zero := new(big.Int).SetBytes(ret[0:32])
first := new(big.Int).SetBytes(ret[32:64])
last := new(big.Int).SetBytes(ret[64:96])
beyond := new(big.Int).SetBytes(ret[96:128])
if zero.Sign() != 0 || beyond.Sign() != 0 {
t.Fatalf("expected zeroes, got %x %x", ret[0:32], ret[96:128])
}
if first.Uint64() != 9999 {
t.Fatalf("first block should be 9999, got %d (%x)", first, ret[32:64])
}
if last.Uint64() != 1808 {
t.Fatalf("last block should be 1808, got %d (%x)", last, ret[64:96])
}
}

// benchmarkNonModifyingCode benchmarks code, but if the code modifies the
// state, this should not be used, since it does not reset the state between runs.
func benchmarkNonModifyingCode(b *testing.B, gas uint64, code []byte, name string) { //nolint:unparam
Expand Down
2 changes: 1 addition & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ const (
var BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")

// EIP-2935: Historical block hashes in state
var HistoryStorageAddress = common.HexToAddress("0x25a219378dad9b3503c8268c9ca836a52427a4fb")
var HistoryStorageAddress = common.HexToAddress("0x0aae40965e6800cd9b1f4b05ff21581047e3f91e")

// EIP-7002: Execution layer triggerable withdrawals
var WithdrawalRequestAddress = common.HexToAddress("0x00A3ca265EBcb825B45F985A16CEFB49958cE017")
Expand Down
5 changes: 5 additions & 0 deletions tests/exec_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func TestExecutionSpec(t *testing.T) {

dir := filepath.Join(".", "execution-spec-tests")

// TODO(yperbasis) make it work
bt.skipLoad(`^prague/eip2935_historical_block_hashes_from_state/block_hashes/block_hashes_history.json`)
bt.skipLoad(`^prague/eip7251_consolidations/`)
bt.skipLoad(`^prague/eip7685_general_purpose_el_requests/`)

checkStateRoot := true

bt.walk(t, dir, func(t *testing.T, name string, test *BlockTest) {
Expand Down
Loading
Loading