Skip to content

unlimit code size #76

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions core/rawdb/accessors_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package rawdb

import (
"encoding/binary"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -48,6 +50,16 @@ func ReadCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) []byte {
return data
}

// ReadCodeSize retrieves the contract code size of the provided code hash.
// Return 0 if not found
func ReadCodeSize(db ethdb.KeyValueReader, hash common.Hash) int {
data, _ := db.Get(codeSizeKey(hash))
if len(data) != 4 {
return 0
}
return int(binary.BigEndian.Uint32(data))
}

// ReadTrieNode retrieves the trie node of the provided hash.
func ReadTrieNode(db ethdb.KeyValueReader, hash common.Hash) []byte {
data, _ := db.Get(hash.Bytes())
Expand Down Expand Up @@ -96,6 +108,12 @@ func WriteCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) {
if err := db.Put(codeKey(hash), code); err != nil {
log.Crit("Failed to store contract code", "err", err)
}

var sizeData [4]byte
binary.BigEndian.PutUint32(sizeData[:], uint32(len(code)))
if err := db.Put(codeSizeKey(hash), sizeData[:]); err != nil {
log.Crit("Failed to store contract code size", "err", err)
}
}

// WriteTrieNode writes the provided trie node database.
Expand Down
6 changes: 6 additions & 0 deletions core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ var (
SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value
CodePrefix = []byte("c") // CodePrefix + code hash -> account code
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
CodeSizePrefix = []byte("s") // CodePrefixSize

PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage
configPrefix = []byte("ethereum-config-") // config prefix for the db
Expand Down Expand Up @@ -230,6 +231,11 @@ func codeKey(hash common.Hash) []byte {
return append(CodePrefix, hash.Bytes()...)
}

// codeSizekey = CodeSizePreifx + hash
func codeSizeKey(hash common.Hash) []byte {
return append(CodeSizePrefix, hash.Bytes()...)
}

// IsCodeKey reports whether the given byte slice is the key of contract code,
// if so return the raw code hash as well.
func IsCodeKey(key []byte) (bool, []byte) {
Expand Down
6 changes: 6 additions & 0 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
return cached.(int), nil
}

size := rawdb.ReadCodeSize(db.db.DiskDB(), codeHash)
if size != 0 {
return size, nil
}

code, err := db.ContractCode(addrHash, codeHash)
return len(code), err
}
Expand Down
6 changes: 3 additions & 3 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
ret, err := evm.interpreter.Run(contract, nil, false)

// Check whether the max code size has been exceeded, assign err if the case.
if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
err = ErrMaxCodeSizeExceeded
}
// if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
// err = ErrMaxCodeSizeExceeded
// }

// Reject code starting with 0xEF if EIP-3541 is enabled.
if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon {
Expand Down
25 changes: 25 additions & 0 deletions core/vm/gas_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@ func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
return gas, nil
}

func addGasExtraCodeSize(evm *EVM, address common.Address, gas uint64) (uint64, bool) {
codeSize := evm.StateDB.GetCodeSize(address)
if codeSize <= params.CodeSizeUnit {
return gas, false
}

extraGas := (uint64(codeSize) - 1) / params.CodeSizeUnit * params.CallGasEIP150
return math.SafeAdd(gas, extraGas)
}

func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
gas uint64
Expand Down Expand Up @@ -357,6 +367,9 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = addGasExtraCodeSize(evm, address, gas); overflow {
return 0, ErrGasUintOverflow
}
return gas, nil
}

Expand All @@ -368,6 +381,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
var (
gas uint64
overflow bool
address = common.Address(stack.Back(1).Bytes20())
)
if stack.Back(2).Sign() != 0 {
gas += params.CallValueTransferGas
Expand All @@ -382,10 +396,14 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = addGasExtraCodeSize(evm, address, gas); overflow {
return 0, ErrGasUintOverflow
}
return gas, nil
}

func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
address := common.Address(stack.Back(1).Bytes20())
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
Expand All @@ -398,10 +416,14 @@ func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = addGasExtraCodeSize(evm, address, gas); overflow {
return 0, ErrGasUintOverflow
}
return gas, nil
}

func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
address := common.Address(stack.Back(1).Bytes20())
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
Expand All @@ -414,6 +436,9 @@ func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = addGasExtraCodeSize(evm, address, gas); overflow {
return 0, ErrGasUintOverflow
}
return gas, nil
}

Expand Down
7 changes: 7 additions & 0 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,13 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
uint64CodeOffset = 0xffffffffffffffff
}
addr := common.Address(a.Bytes20())
codeSize := interpreter.evm.StateDB.GetCodeSize(addr)
if codeSize > params.CodeSizeUnit {
extraGas := (uint64(codeSize - 1)) / params.CodeSizeUnit * params.ExtcodeSizeGasEIP150
if !scope.Contract.UseGas(extraGas) {
return nil, ErrOutOfGas
}
}
codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64())
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)

Expand Down
2 changes: 1 addition & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const (
ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.

MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
CodeSizeUnit = 24576 // Code size unit for gas metering.

// Precompiled contract gas prices

Expand Down