Skip to content

Commit

Permalink
Implement EXTCODE* changes for pdn-5 (#13106)
Browse files Browse the repository at this point in the history
See ethereum/EIPs#8969
Issue board: #12401
  • Loading branch information
somnathb1 authored Jan 14, 2025
1 parent d2fc77c commit d1d1894
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 98 deletions.
18 changes: 0 additions & 18 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,24 +360,6 @@ func (sdb *IntraBlockState) ResolveCode(addr libcommon.Address) ([]byte, error)
return sdb.GetCode(addr)
}

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

return size, nil
}

func (sdb *IntraBlockState) GetDelegatedDesignation(addr libcommon.Address) (libcommon.Address, bool, error) {
// eip-7702
code, err := 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 @@ -387,7 +387,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
15 changes: 8 additions & 7 deletions core/types/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

type Authorization struct {
ChainID uint64
ChainID uint256.Int
Address libcommon.Address
Nonce uint64
YParity uint8
Expand All @@ -41,7 +41,7 @@ func (ath *Authorization) RecoverSigner(data *bytes.Buffer, b []byte) (*libcommo
return nil, errors.New("failed assertion: auth.nonce < 2**64 - 1")
}

authLen := rlp.U64Len(ath.ChainID)
authLen := (1 + rlp.Uint256LenExcludingHead(&ath.ChainID))
authLen += 1 + length.Addr
authLen += rlp.U64Len(ath.Nonce)

Expand All @@ -50,7 +50,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 := rlp.EncodeUint256(&ath.ChainID, data, b); err != nil {
return nil, err
}

Expand Down Expand Up @@ -99,7 +99,7 @@ func RecoverSignerFromRLP(rlp []byte, yParity uint8, r uint256.Int, s uint256.In
}

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

Expand Down Expand Up @@ -127,10 +127,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 @@ -193,7 +194,7 @@ func encodeAuthorizations(authorizations []Authorization, w io.Writer, b []byte)
}

// 1. encode ChainId
if err := rlp.EncodeInt(authorizations[i].ChainID, w, b); err != nil {
if err := rlp.EncodeUint256(&authorizations[i].ChainID, w, b); err != nil {
return err
}
// 2. encode Address
Expand Down
2 changes: 1 addition & 1 deletion core/types/encdec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,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 @@ -68,7 +68,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 @@ -77,7 +77,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 @@ -89,10 +89,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 @@ -326,9 +326,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 @@ -136,7 +136,6 @@ type IntraBlockState interface {
// eip-7702; delegated designations
ResolveCodeHash(common.Address) (common.Hash, error)
ResolveCode(common.Address) ([]byte, error)
ResolveCodeSize(common.Address) (int, error)
GetDelegatedDesignation(common.Address) (common.Address, bool, error)

AddRefund(uint64)
Expand Down
31 changes: 27 additions & 4 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,20 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte

func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.Peek()
codeSize, err := interpreter.evm.IntraBlockState().ResolveCodeSize(slot.Bytes20())
addr := slot.Bytes20()
codeSize, err := interpreter.evm.IntraBlockState().GetCodeSize(addr)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err)
}
if codeSize == types.DelegateDesignationCodeSize {
_, ok, err := interpreter.evm.IntraBlockState().GetDelegatedDesignation(addr)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err)
}
if ok {
codeSize = 2 // first two bytes only: EIP-7702
}
}
slot.SetUint64(uint64(codeSize))
return nil, nil
}
Expand Down Expand Up @@ -416,10 +426,14 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
addr := libcommon.Address(a.Bytes20())
len64 := length.Uint64()

code, err := interpreter.evm.IntraBlockState().ResolveCode(addr)
code, err := interpreter.evm.IntraBlockState().GetCode(addr)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err)
}
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 @@ -473,9 +487,18 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
if empty {
slot.Clear()
} else {
codeHash, err := interpreter.evm.IntraBlockState().ResolveCodeHash(address)
var codeHash libcommon.Hash
_, ok, err := interpreter.evm.IntraBlockState().GetDelegatedDesignation(address)
if err != nil {
return nil, err
return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err)
}
if ok {
codeHash = params.DelegatedCodeHash
} else {
codeHash, err = interpreter.evm.IntraBlockState().GetCodeHash(address)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err)
}
}
slot.SetBytes(codeHash.Bytes())
}
Expand Down
60 changes: 0 additions & 60 deletions core/vm/operations_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,63 +317,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
}
dd, ok, err := evm.intraBlockState.GetDelegatedDesignation(addr)
if err != nil {
return 0, err
}
if 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
dd, ok, err := evm.intraBlockState.GetDelegatedDesignation(addr)
if err != nil {
return 0, err
}
if 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 @@ -186,6 +186,7 @@ const (

// EIP-7702: Set EOA account code
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 d1d1894

Please sign in to comment.