Skip to content

Commit

Permalink
Implement EXTCODE* changes for pdn-5 (#13106) (#13448)
Browse files Browse the repository at this point in the history
See ethereum/EIPs#8969
Issue board: #12401

Cherry pick #13106
  • Loading branch information
somnathb1 authored Jan 16, 2025
1 parent e6b7ad8 commit 07c6e9c
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 86 deletions.
11 changes: 0 additions & 11 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,17 +278,6 @@ func (sdb *IntraBlockState) ResolveCode(addr libcommon.Address) []byte {
return sdb.GetCode(addr)
}

func (sdb *IntraBlockState) ResolveCodeSize(addr libcommon.Address) int {
// eip-7702
size := sdb.GetCodeSize(addr)
if size == types.DelegateDesignationCodeSize {
// might be delegated designation
return len(sdb.ResolveCode(addr))
}

return size
}

func (sdb *IntraBlockState) GetDelegatedDesignation(addr libcommon.Address) (libcommon.Address, bool) {
// eip-7702
code := sdb.GetCode(addr)
Expand Down
2 changes: 1 addition & 1 deletion core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype
data.Reset()

// 1. chainId check
if auth.ChainID != 0 && (!rules.ChainID.IsUint64() || rules.ChainID.Uint64() != auth.ChainID) {
if !auth.ChainID.IsZero() && rules.ChainID.String() != auth.ChainID.String() {
log.Debug("invalid chainID, skipping", "chainId", auth.ChainID, "auth index", i)
continue
}
Expand Down
17 changes: 9 additions & 8 deletions core/types/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

type Authorization struct {
ChainID uint64
ChainID uint256.Int
Address libcommon.Address
Nonce uint64
YParity uint8
Expand All @@ -38,7 +38,7 @@ func (ath *Authorization) copy() *Authorization {
}

func (ath *Authorization) RecoverSigner(data *bytes.Buffer, b []byte) (*libcommon.Address, error) {
authLen := rlp2.U64Len(ath.ChainID)
authLen := (1 + rlp.Uint256LenExcludingHead(&ath.ChainID))
authLen += (1 + length.Addr)
authLen += rlp2.U64Len(ath.Nonce)

Expand All @@ -47,7 +47,7 @@ func (ath *Authorization) RecoverSigner(data *bytes.Buffer, b []byte) (*libcommo
}

// chainId, address, nonce
if err := rlp.EncodeInt(ath.ChainID, data, b); err != nil {
if err := ath.ChainID.EncodeRLP(data); err != nil {
return nil, err
}

Expand Down Expand Up @@ -96,9 +96,9 @@ func (ath *Authorization) RecoverSigner(data *bytes.Buffer, b []byte) (*libcommo
}

func authorizationSize(auth Authorization) (authLen int) {
authLen = rlp2.U64Len(auth.ChainID)
authLen = (1 + rlp.Uint256LenExcludingHead(&auth.ChainID))
authLen += rlp2.U64Len(auth.Nonce)
authLen += (1 + length.Addr)
authLen += 1 + length.Addr

authLen += rlp2.U64Len(uint64(auth.YParity)) + (1 + rlp.Uint256LenExcludingHead(&auth.R)) + (1 + rlp.Uint256LenExcludingHead(&auth.S))

Expand All @@ -124,10 +124,11 @@ func decodeAuthorizations(auths *[]Authorization, s *rlp.Stream) error {
for _, err = s.List(); err == nil; _, err = s.List() {
auth := Authorization{}

// chainId
if auth.ChainID, err = s.Uint(); err != nil {
var chainId []byte
if chainId, err = s.Uint256Bytes(); err != nil {
return err
}
auth.ChainID.SetBytes(chainId)

// address
if b, err = s.Bytes(); err != nil {
Expand Down Expand Up @@ -191,7 +192,7 @@ func encodeAuthorizations(authorizations []Authorization, w io.Writer, b []byte)
}

// 1. encode ChainId
if err := rlp.EncodeInt(auth.ChainID, w, b); err != nil {
if err := auth.ChainID.EncodeRLP(w); err != nil {
return err
}
// 2. encode Address
Expand Down
7 changes: 6 additions & 1 deletion core/types/encdec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func (tr *TRand) RandUint64() *uint64 {
return &a
}

func (tr *TRand) RandUint256() *uint256.Int {
a := new(uint256.Int).SetBytes(tr.RandBytes(tr.RandIntInRange(1, 32)))
return a
}

func (tr *TRand) RandBig() *big.Int {
return big.NewInt(int64(tr.rnd.Int()))
}
Expand Down Expand Up @@ -120,7 +125,7 @@ func (tr *TRand) RandAuthorizations(size int) []Authorization {
auths := make([]Authorization, size)
for i := 0; i < size; i++ {
auths[i] = Authorization{
ChainID: *tr.RandUint64(),
ChainID: *tr.RandUint256(),
Address: tr.RandAddress(),
Nonce: *tr.RandUint64(),
YParity: uint8(*tr.RandUint64()),
Expand Down
10 changes: 7 additions & 3 deletions core/types/transaction_marshalling.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type txJSON struct {
}

type JsonAuthorization struct {
ChainID hexutil.Uint64 `json:"chainId"`
ChainID hexutil.Big `json:"chainId"`
Address libcommon.Address `json:"address"`
Nonce hexutil.Uint64 `json:"nonce"`
V hexutil.Uint64 `json:"v"`
Expand All @@ -60,7 +60,7 @@ type JsonAuthorization struct {
}

func (a JsonAuthorization) FromAuthorization(authorization Authorization) JsonAuthorization {
a.ChainID = (hexutil.Uint64)(authorization.ChainID)
a.ChainID = hexutil.Big(*authorization.ChainID.ToBig())
a.Address = authorization.Address
a.Nonce = (hexutil.Uint64)(authorization.Nonce)

Expand All @@ -72,10 +72,14 @@ func (a JsonAuthorization) FromAuthorization(authorization Authorization) JsonAu

func (a JsonAuthorization) ToAuthorization() (Authorization, error) {
auth := Authorization{
ChainID: a.ChainID.Uint64(),
Address: a.Address,
Nonce: a.Nonce.Uint64(),
}
chainId, overflow := uint256.FromBig((*big.Int)(&a.ChainID))
if overflow {
return auth, errors.New("chainId in authorization does not fit in 256 bits")
}
auth.ChainID = *chainId
yParity := a.V.Uint64()
if yParity >= 1<<8 {
return auth, errors.New("y parity in authorization does not fit in 8 bits")
Expand Down
3 changes: 0 additions & 3 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,6 @@ func enable7516(jt *JumpTable) {
}

func enable7702(jt *JumpTable) {
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP7702
jt[EXTCODESIZE].dynamicGas = gasEip7702CodeCheck
jt[EXTCODEHASH].dynamicGas = gasEip7702CodeCheck
jt[CALL].dynamicGas = gasCallEIP7702
jt[CALLCODE].dynamicGas = gasCallCodeEIP7702
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
Expand Down
1 change: 0 additions & 1 deletion core/vm/evmtypes/evmtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ type IntraBlockState interface {
// eip-7702; delegated designations
ResolveCodeHash(common.Address) common.Hash
ResolveCode(common.Address) []byte
ResolveCodeSize(common.Address) int
GetDelegatedDesignation(common.Address) (common.Address, bool)

AddRefund(uint64)
Expand Down
29 changes: 25 additions & 4 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package vm

import (
"errors"
"fmt"
"math"

Expand Down Expand Up @@ -374,7 +375,15 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte

func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.Peek()
slot.SetUint64(uint64(interpreter.evm.IntraBlockState().ResolveCodeSize(slot.Bytes20())))
addr := slot.Bytes20()
codeSize := interpreter.evm.IntraBlockState().GetCodeSize(addr)
if codeSize == types.DelegateDesignationCodeSize {
_, ok := interpreter.evm.IntraBlockState().GetDelegatedDesignation(addr)
if ok {
codeSize = 2 // first two bytes only: EIP-7702
}
}
slot.SetUint64(uint64(codeSize))
return nil, nil
}

Expand Down Expand Up @@ -411,7 +420,12 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
addr := libcommon.Address(a.Bytes20())
len64 := length.Uint64()

codeCopy := getDataBig(interpreter.evm.IntraBlockState().ResolveCode(addr), &codeOffset, len64)
code := interpreter.evm.IntraBlockState().GetCode(addr)
if _, ok := types.ParseDelegation(code); ok {
code = append([]byte{}, (params.DelegatedDesignationPrefix[0:2])...)
}

codeCopy := getDataBig(code, &codeOffset, len64)
scope.Memory.Set(memOffset.Uint64(), len64, codeCopy)
return nil, nil
}
Expand Down Expand Up @@ -460,7 +474,14 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
if interpreter.evm.IntraBlockState().Empty(address) {
slot.Clear()
} else {
slot.SetBytes(interpreter.evm.IntraBlockState().ResolveCodeHash(address).Bytes())
var codeHash libcommon.Hash
_, ok := interpreter.evm.IntraBlockState().GetDelegatedDesignation(address)
if ok {
codeHash = params.DelegatedCodeHash
} else {
codeHash = interpreter.evm.IntraBlockState().GetCodeHash(address)
}
slot.SetBytes(codeHash.Bytes())
}
return nil, nil
}
Expand Down Expand Up @@ -519,7 +540,7 @@ func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
var overflow bool
v, overflow = uint256.FromBig(interpreter.evm.Context.Difficulty)
if overflow {
return nil, fmt.Errorf("interpreter.evm.Context.Difficulty higher than 2^256-1")
return nil, errors.New("interpreter.evm.Context.Difficulty higher than 2^256-1")
}
}
scope.Stack.Push(v)
Expand Down
56 changes: 2 additions & 54 deletions core/vm/operations_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
}

// Check if code is a delegation and if so, charge for resolution.
if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok {
dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr)
if ok {
var ddCost uint64
if evm.intraBlockState.AddAddressToAccessList(dd) {
ddCost = params.ColdAccountAccessCostEIP2929
Expand Down Expand Up @@ -296,56 +297,3 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
return gas, nil
}
}

func gasEip7702CodeCheck(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := libcommon.Address(stack.Peek().Bytes20())
// The warm storage read cost is already charged as constantGas
// Check slot presence in the access list
var cost uint64
if evm.intraBlockState.AddAddressToAccessList(addr) {
// Check if code is a delegation and if so, charge for resolution
cost = params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
}

if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok {
if evm.intraBlockState.AddAddressToAccessList(dd) {
cost += params.ColdAccountAccessCostEIP2929
} else {
cost += params.WarmStorageReadCostEIP2929
}
}

return cost, nil
}

func gasExtCodeCopyEIP7702(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) {
// memory expansion first (dynamic part of pre-2929 implementation)
gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
if err != nil {
return 0, err
}
addr := libcommon.Address(stack.Peek().Bytes20())
// Check slot presence in the access list
if evm.intraBlockState.AddAddressToAccessList(addr) {
var overflow bool
// We charge (cold-warm), since 'warm' is already charged as constantGas
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
return 0, ErrGasUintOverflow
}
}

// Check if addr has a delegation and if so, charge for resolution
if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok {
var overflow bool
if evm.intraBlockState.AddAddressToAccessList(dd) {
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929); overflow {
return 0, ErrGasUintOverflow
}
} else {
if gas, overflow = math.SafeAdd(gas, params.WarmStorageReadCostEIP2929); overflow {
return 0, ErrGasUintOverflow
}
}
}
return gas, nil
}
1 change: 1 addition & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ const (
)

var DelegatedDesignationPrefix = []byte{0xef, 0x01, 0x00}
var DelegatedCodeHash = common.HexToHash("0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329")

// EIP-4788: Beacon block root in the EVM
var BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
Expand Down

0 comments on commit 07c6e9c

Please sign in to comment.