nimbus-eth1/nimbus/evm/tracer/access_list_tracer.nim

78 lines
2.3 KiB
Nim

# Nimbus
# Copyright (c) 2023-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.
import
std/[sets],
eth/common/eth_types as common,
".."/[types, stack],
../interpreter/op_codes,
../../db/access_list,
../../errors
type
AccessListTracer* = ref object of TracerRef
list: access_list.AccessList
excl: HashSet[EthAddress]
proc new*(T: type AccessListTracer,
acl: common.AccessList,
sender: EthAddress,
to: EthAddress,
precompiles: openArray[EthAddress]): T =
let act = T()
act.excl.incl sender
act.excl.incl to
for address in precompiles:
act.excl.incl address
for acp in acl:
if acp.address notin act.excl:
act.list.add acp.address
for slot in acp.storageKeys:
act.list.add(acp.address, UInt256.fromBytesBE(slot))
act
# Opcode level
method captureOpStart*(act: AccessListTracer, c: Computation,
fixed: bool, pc: int, op: Op, gas: GasInt,
depth: int): int {.gcsafe.} =
let stackLen = c.stack.len
try:
if (op in [Sload, Sstore]) and (stackLen >= 1):
let slot = c.stack.peekInt()
act.list.add(c.msg.contractAddress, slot)
if (op in [ExtCodeCopy, ExtCodeHash, ExtCodeSize, Balance, SelfDestruct]) and (stackLen >= 1):
let address = c.stack.peekAddress()
if address notin act.excl:
act.list.add address
if (op in [DelegateCall, Call, StaticCall, CallCode]) and (stackLen >= 5):
let address = c.stack[^2, EthAddress]
if address notin act.excl:
act.list.add address
except InsufficientStack as exc:
# should not raise, because we already check the stack len
# this try..except block is to prevent unlisted exception error
discard exc
except ValueError as exc:
discard exc
# AccessListTracer is not using captureOpEnd
# no need to return op index
func equal*(ac: AccessListTracer, other: AccessListTracer): bool =
ac.list.equal(other.list)
func accessList*(ac: AccessListTracer): common.AccessList =
ac.list.getAccessList()