Bugfix: Off by 1 in EIP-170 code size checks in stateless

Fixes an off by 1 error where `EIP170_CODE_SIZE_LIMIT` was being treated as the
lowest invalid value by EVM code, but the highest valid value by witness code.

To remove confusion, this is renamed to `EIP170_MAX_CODE_SIZE` with value
0x6000, which matches the name (`MAX_CODE_SIZE`) and value used for this limit
in [EIP-170](https://eips.ethereum.org/EIPS/eip-170).

Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
Jamie Lokier 2021-10-06 20:43:18 +01:00
parent 40fbed49cf
commit 242dfdd5ac
No known key found for this signature in database
GPG Key ID: CBC25C68435C30A2
6 changed files with 14 additions and 13 deletions

View File

@ -54,9 +54,10 @@ const
## Fork specific constants
# See: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md
# and: https://github.com/ethereum/EIPs/issues/170
EIP170_CODE_SIZE_LIMIT* = 24577
# See EIP-170 (https://eips.ethereum.org/EIPS/eip-170). Maximum code size
# that can be stored for a new contract. Init code when creating a new
# contract is not subject to this limit.
EIP170_MAX_CODE_SIZE* = 0x6000
# EIP
MaxPrecompilesAddr* = 0xFFFF

View File

@ -232,8 +232,9 @@ proc writeContract*(c: Computation, fork: Fork): bool {.gcsafe.} =
let contractCode = c.output
if contractCode.len == 0: return
if fork >= FkSpurious and contractCode.len >= EIP170_CODE_SIZE_LIMIT:
debug "Contract code size exceeds EIP170", limit=EIP170_CODE_SIZE_LIMIT, actual=contractCode.len
if fork >= FkSpurious and contractCode.len > EIP170_MAX_CODE_SIZE:
debug "Contract code size exceeds EIP170",
max = EIP170_MAX_CODE_SIZE, actual = contractCode.len
return false
if fork >= FkLondon and contractCode[0] == 0xEF.byte:

View File

@ -169,10 +169,9 @@ proc writeContract*(c: Computation, fork: Fork): bool {.gcsafe.} =
let contractCode = c.output
if contractCode.len == 0: return
if fork >= FkSpurious and contractCode.len >= EIP170_CODE_SIZE_LIMIT:
if fork >= FkSpurious and contractCode.len > EIP170_MAX_CODE_SIZE:
debug "Contract code size exceeds EIP170",
limit = EIP170_CODE_SIZE_LIMIT,
actual = contractCode.len
max = EIP170_MAX_CODE_SIZE, actual = contractCode.len
return false
if fork >= FkLondon and contractCode[0] == 0xEF.byte:

View File

@ -174,7 +174,7 @@ proc writeByteCode(wb: var WitnessBuilder, kd: KeyData, acc: Account) =
# in current block execution
wb.writeByte(CodeUntouched, "codeType")
let code = get(wb.db, contractHashKey(acc.codeHash).toOpenArray)
if wfEIP170 in wb.flags and code.len > EIP170_CODE_SIZE_LIMIT:
if wfEIP170 in wb.flags and code.len > EIP170_MAX_CODE_SIZE:
raise newException(ContractCodeError, "code len exceed EIP170 code size limit")
wb.writeUVarint32(code.len, "codeLen")
wb.writeHashNode(acc.codeHash.data, "codeHash")
@ -189,7 +189,7 @@ proc writeByteCode(wb: var WitnessBuilder, kd: KeyData, acc: Account) =
# the account have code and the EVM use it
let code = get(wb.db, contractHashKey(acc.codeHash).toOpenArray)
if wfEIP170 in wb.flags and code.len > EIP170_CODE_SIZE_LIMIT:
if wfEIP170 in wb.flags and code.len > EIP170_MAX_CODE_SIZE:
raise newException(ContractCodeError, "code len exceed EIP170 code size limit")
wb.writeUVarint32(code.len, "codeLen")
wb.write(code, "code")

View File

@ -370,7 +370,7 @@ proc readAddress(t: var TreeBuilder): Hash256 =
proc readCodeLen(t: var TreeBuilder): int =
let codeLen = t.readUVarint32()
if wfEIP170 in t.flags and codeLen > EIP170_CODE_SIZE_LIMIT:
if wfEIP170 in t.flags and codeLen > EIP170_MAX_CODE_SIZE:
raise newException(ContractCodeError, "code len exceed EIP170 code size limit: " & $codeLen)
t.keys[^1].codeLen = codeLen.int
result = codeLen.int

View File

@ -162,7 +162,7 @@ proc writeByteCode(wb: var WitnessBuilder, kd: KeyData, acc: Account, depth: int
# in current block execution
wb.writeByte(CodeUntouched)
let code = get(wb.db, contractHashKey(acc.codeHash).toOpenArray)
if wfEIP170 in wb.flags and code.len > EIP170_CODE_SIZE_LIMIT:
if wfEIP170 in wb.flags and code.len > EIP170_MAX_CODE_SIZE:
raise newException(ContractCodeError, "code len exceed EIP170 code size limit")
wb.writeUVarint32(code.len)
wb.writeHashNode(acc.codeHash.data, depth, false)
@ -177,7 +177,7 @@ proc writeByteCode(wb: var WitnessBuilder, kd: KeyData, acc: Account, depth: int
# the account have code and the EVM use it
let code = get(wb.db, contractHashKey(acc.codeHash).toOpenArray)
if wfEIP170 in wb.flags and code.len > EIP170_CODE_SIZE_LIMIT:
if wfEIP170 in wb.flags and code.len > EIP170_MAX_CODE_SIZE:
raise newException(ContractCodeError, "code len exceed EIP170 code size limit")
wb.writeUVarint32(code.len)
wb.write(code)