nimbus-eth1/nimbus/evm/interpreter/op_handlers/oph_envinfo.nim

389 lines
12 KiB
Nim
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Environmental Information
## ==============================================
##
{.push raises: [].}
import
../../evm_errors,
../../code_stream,
../../computation,
../../memory,
../../stack,
../gas_costs,
../op_codes,
./oph_defs,
./oph_helpers,
eth/common,
stew/assign2,
stint
when not defined(evmc_enabled):
import ../../state
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
proc addressOp(cpt: VmCpt): EvmResultVoid =
## 0x30, Get address of currently executing account.
cpt.stack.push cpt.msg.contractAddress
# ------------------
proc balanceOp(cpt: VmCpt): EvmResultVoid =
## 0x31, Get balance of the given account.
template balance256(address): auto =
cpt.getBalance(address)
cpt.stack.unaryAddress(balance256)
proc balanceEIP2929Op(cpt: VmCpt): EvmResultVoid =
## 0x31, EIP292: Get balance of the given account for Berlin and later
template balanceEIP2929(address): auto =
let gasCost = cpt.gasEip2929AccountCheck(address)
? cpt.opcodeGasCost(Balance, gasCost, reason = "Balance EIP2929")
cpt.getBalance(address)
cpt.stack.unaryAddress(balanceEIP2929)
# ------------------
proc originOp(cpt: VmCpt): EvmResultVoid =
## 0x32, Get execution origination address.
cpt.stack.push cpt.getOrigin()
proc callerOp(cpt: VmCpt): EvmResultVoid =
## 0x33, Get caller address.
cpt.stack.push cpt.msg.sender
proc callValueOp(cpt: VmCpt): EvmResultVoid =
## 0x34, Get deposited value by the instruction/transaction
## responsible for this execution
cpt.stack.push cpt.msg.value
proc callDataLoadOp(cpt: VmCpt): EvmResultVoid =
## 0x35, Get input data of current environment
? cpt.stack.lsCheck(1)
let start = cpt.stack.lsPeekMemRef(^1)
if start >= cpt.msg.data.len:
cpt.stack.lsTop 0
return ok()
# If the data does not take 32 bytes, pad with zeros
let
endRange = min(cpt.msg.data.len - 1, start + 31)
presentBytes = endRange - start
# We rely on value being initialized with 0 by default
var value: array[32, byte]
assign(value.toOpenArray(0, presentBytes), cpt.msg.data.toOpenArray(start, endRange))
cpt.stack.lsTop value
ok()
proc callDataSizeOp(cpt: VmCpt): EvmResultVoid =
## 0x36, Get size of input data in current environment.
cpt.stack.push cpt.msg.data.len.u256
proc callDataCopyOp(cpt: VmCpt): EvmResultVoid =
## 0x37, Copy input data in current environment to memory.
? cpt.stack.lsCheck(3)
let
memPos = cpt.stack.lsPeekMemRef(^1)
copyPos = cpt.stack.lsPeekMemRef(^2)
len = cpt.stack.lsPeekMemRef(^3)
cpt.stack.lsShrink(3)
? cpt.opcodeGasCost(CallDataCopy,
cpt.gasCosts[CallDataCopy].m_handler(cpt.memory.len, memPos, len),
reason = "CallDataCopy fee")
cpt.memory.writePadded(cpt.msg.data, memPos, copyPos, len)
ok()
proc codeSizeOp(cpt: VmCpt): EvmResultVoid =
## 0x38, Get size of code running in current environment.
cpt.stack.push cpt.code.len
proc codeCopyOp(cpt: VmCpt): EvmResultVoid =
## 0x39, Copy code running in current environment to memory.
? cpt.stack.lsCheck(3)
let
memPos = cpt.stack.lsPeekMemRef(^1)
copyPos = cpt.stack.lsPeekMemRef(^2)
len = cpt.stack.lsPeekMemRef(^3)
cpt.stack.lsShrink(3)
? cpt.opcodeGasCost(CodeCopy,
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "CodeCopy fee")
cpt.memory.writePadded(cpt.code.bytes, memPos, copyPos, len)
ok()
proc gasPriceOp(cpt: VmCpt): EvmResultVoid =
## 0x3A, Get price of gas in current environment.
cpt.stack.push cpt.getGasPrice()
# -----------
proc extCodeSizeOp(cpt: VmCpt): EvmResultVoid =
## 0x3b, Get size of an account's code
template ecs256(address): auto =
cpt.getCodeSize(address)
cpt.stack.unaryAddress(ecs256)
proc extCodeSizeEIP2929Op(cpt: VmCpt): EvmResultVoid =
## 0x3b, Get size of an account's code
template ecsEIP2929(address): auto =
let gasCost = cpt.gasEip2929AccountCheck(address)
? cpt.opcodeGasCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
cpt.getCodeSize(address)
cpt.stack.unaryAddress(ecsEIP2929)
# -----------
proc extCodeCopyOp(cpt: VmCpt): EvmResultVoid =
## 0x3c, Copy an account's code to memory.
? cpt.stack.lsCheck(4)
let
address = cpt.stack.lsPeekAddress(^1)
memPos = cpt.stack.lsPeekMemRef(^2)
codePos = cpt.stack.lsPeekMemRef(^3)
len = cpt.stack.lsPeekMemRef(^4)
cpt.stack.lsShrink(4)
? cpt.opcodeGasCost(ExtCodeCopy,
cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "ExtCodeCopy fee")
let code = cpt.getCode(address)
cpt.memory.writePadded(code.bytes, memPos, codePos, len)
ok()
proc extCodeCopyEIP2929Op(cpt: VmCpt): EvmResultVoid =
## 0x3c, Copy an account's code to memory.
? cpt.stack.lsCheck(4)
let
address = cpt.stack.lsPeekAddress(^1)
memPos = cpt.stack.lsPeekMemRef(^2)
codePos = cpt.stack.lsPeekMemRef(^3)
len = cpt.stack.lsPeekMemRef(^4)
gasCost = cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len) +
cpt.gasEip2929AccountCheck(address)
cpt.stack.lsShrink(4)
? cpt.opcodeGasCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
let code = cpt.getCode(address)
cpt.memory.writePadded(code.bytes(), memPos, codePos, len)
ok()
# -----------
proc returnDataSizeOp(cpt: VmCpt): EvmResultVoid =
## 0x3d, Get size of output data from the previous call from the
## current environment.
cpt.stack.push cpt.returnData.len
proc returnDataCopyOp(cpt: VmCpt): EvmResultVoid =
## 0x3e, Copy output data from the previous call to memory.
? cpt.stack.lsCheck(3)
let
memPos = cpt.stack.lsPeekMemRef(^1)
copyPos = cpt.stack.lsPeekMemRef(^2)
len = cpt.stack.lsPeekMemRef(^3)
gasCost = cpt.gasCosts[ReturnDataCopy].m_handler(
cpt.memory.len, memPos, len)
cpt.stack.lsShrink(3)
? cpt.opcodeGasCost(ReturnDataCopy, gasCost, reason = "returnDataCopy fee")
if copyPos + len > cpt.returnData.len:
return err(opErr(OutOfBounds))
cpt.memory.writePadded(cpt.returnData, memPos, copyPos, len)
ok()
# ---------------
proc extCodeHashOp(cpt: VmCpt): EvmResultVoid =
## 0x3f, Returns the keccak256 hash of a contracts code
template ech256(address): auto =
cpt.getCodeHash(address)
cpt.stack.unaryAddress(ech256)
proc extCodeHashEIP2929Op(cpt: VmCpt): EvmResultVoid =
## 0x3f, EIP2929: Returns the keccak256 hash of a contracts code
template echEIP2929(address): auto =
let gasCost = cpt.gasEip2929AccountCheck(address)
? cpt.opcodeGasCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
cpt.getCodeHash(address)
cpt.stack.unaryAddress(echEIP2929)
# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------
const
VmOpExecEnvInfo*: seq[VmOpExec] = @[
(opCode: Address, ## 0x20, Address
forks: VmOpAllForks,
name: "address",
info: "Get address of currently executing account",
exec: VmOpFn addressOp),
(opCode: Balance, ## 0x31, Balance
forks: VmOpAllForks - VmOpBerlinAndLater,
name: "balance",
info: "Get balance of the given account",
exec: balanceOp),
(opCode: Balance, ## 0x31, Balance for Berlin and later
forks: VmOpBerlinAndLater,
name: "balanceEIP2929",
info: "EIP2929: Get balance of the given account",
exec: balanceEIP2929Op),
(opCode: Origin, ## 0x32, Origination address
forks: VmOpAllForks,
name: "origin",
info: "Get execution origination address",
exec: originOp),
(opCode: Caller, ## 0x33, Caller address
forks: VmOpAllForks,
name: "caller",
info: "Get caller address",
exec: callerOp),
(opCode: CallValue, ## 0x34, Execution deposited value
forks: VmOpAllForks,
name: "callValue",
info: "Get deposited value by the instruction/transaction " &
"responsible for this execution",
exec: callValueOp),
(opCode: CallDataLoad, ## 0x35, Input data
forks: VmOpAllForks,
name: "callDataLoad",
info: "Get input data of current environment",
exec: callDataLoadOp),
(opCode: CallDataSize, ## 0x36, Size of input data
forks: VmOpAllForks,
name: "callDataSize",
info: "Get size of input data in current environment",
exec: callDataSizeOp),
(opCode: CallDataCopy, ## 0x37, Copy input data to memory.
forks: VmOpAllForks,
name: "callDataCopy",
info: "Copy input data in current environment to memory",
exec: callDataCopyOp),
(opCode: CodeSize, ## 0x38, Size of code
forks: VmOpAllForks,
name: "codeSize",
info: "Get size of code running in current environment",
exec: codeSizeOp),
(opCode: CodeCopy, ## 0x39, Copy code to memory.
forks: VmOpAllForks,
name: "codeCopy",
info: "Copy code running in current environment to memory",
exec: codeCopyOp),
(opCode: GasPrice, ## 0x3a, Gas price
forks: VmOpAllForks,
name: "gasPrice",
info: "Get price of gas in current environment",
exec: gasPriceOp),
(opCode: ExtCodeSize, ## 0x3b, Account code size
forks: VmOpAllForks - VmOpBerlinAndLater,
name: "extCodeSize",
info: "Get size of an account's code",
exec: extCodeSizeOp),
(opCode: ExtCodeSize, ## 0x3b, Account code size for Berlin and later
forks: VmOpBerlinAndLater,
name: "extCodeSizeEIP2929",
info: "EIP2929: Get size of an account's code",
exec: extCodeSizeEIP2929Op),
(opCode: ExtCodeCopy, ## 0x3c, Account code copy to memory.
forks: VmOpAllForks - VmOpBerlinAndLater,
name: "extCodeCopy",
info: "Copy an account's code to memory",
exec: extCodeCopyOp),
(opCode: ExtCodeCopy, ## 0x3c, Account Code-copy for Berlin and later
forks: VmOpBerlinAndLater,
name: "extCodeCopyEIP2929",
info: "EIP2929: Copy an account's code to memory",
exec: extCodeCopyEIP2929Op),
(opCode: ReturnDataSize, ## 0x3d, Previous call output data size
forks: VmOpByzantiumAndLater,
name: "returnDataSize",
info: "Get size of output data from the previous call " &
"from the current environment",
exec: returnDataSizeOp),
(opCode: ReturnDataCopy, ## 0x3e, Previous call output data copy to memory
forks: VmOpByzantiumAndLater,
name: "returnDataCopy",
info: "Copy output data from the previous call to memory",
exec: returnDataCopyOp),
(opCode: ExtCodeHash, ## 0x3f, Contract hash
forks: VmOpConstantinopleAndLater - VmOpBerlinAndLater,
name: "extCodeHash",
info: "Returns the keccak256 hash of a contracts code",
exec: extCodeHashOp),
(opCode: ExtCodeHash, ## 0x3f, Contract hash for berlin and later
forks: VmOpBerlinAndLater,
name: "extCodeHashEIP2929",
info: "EIP2929: Returns the keccak256 hash of a contracts code",
exec: extCodeHashEIP2929Op)]
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------