Skip to content

Commit

Permalink
feat: wip events in calltrees
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Jun 24, 2024
1 parent ad6fa2e commit 4f96bd1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
10 changes: 8 additions & 2 deletions evm_trace/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ class Event(BaseModel):
An event emitted during a CALL.
"""

calldata: HexBytes = HexBytes("")
"""Event calldata (inputs)."""
data: list[HexBytes] = []
"""The remaining event data besides the topics."""

selector: HexBytes
"""The selector hash of the event."""

topics: list[HexBytes] = []
"""Event topics."""
#
# def __repr__(self) -> str:
# return f"{self.calldata.hex()}"


class CallTreeNode(BaseModel):
"""
Expand Down
42 changes: 39 additions & 3 deletions evm_trace/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@ def get_tree_display(call: "CallTreeNode") -> str:


class TreeRepresentation:
FILE_MIDDLE_PREFIX = "├──"
FILE_LAST_PREFIX = "└──"
"""
A class for creating a simple tree-representation of a call-tree node.
**NOTE**: We purposely are not using the rich library here to keep
evm-trace small and simple while sill offering a nice stringified
version of a :class:`~evm_trace.base.CallTreeNode`.
"""

MIDDLE_PREFIX = "├──"
LAST_PREFIX = "└──"
PARENT_PREFIX_MIDDLE = " "
PARENT_PREFIX_LAST = "│ "

Expand All @@ -32,10 +40,17 @@ def __init__(

@property
def depth(self) -> int:
"""
The depth in the call tree, such as the
number of calls deep.
"""
return self.call.depth

@property
def title(self) -> str:
"""
The title of the node representation, including address, calldata, and return-data.
"""
call_type = self.call.call_type.value
address_hex_str = self.call.address.hex() if self.call.address else None

Expand Down Expand Up @@ -81,6 +96,15 @@ def make_tree(
parent: Optional["TreeRepresentation"] = None,
is_last: bool = False,
) -> Iterator["TreeRepresentation"]:
"""
Create a node representation object from a :class:`~evm_trace.base.CallTreeNode`.
Args:
root (:class:`~evm_trace.base.CallTreeNode`): The call-tree node to display.
parent (Optional[:class:`~evm_trace.display.TreeRepresentation`]): The parent
node of this node.
is_last (bool): True if a leaf-node.
"""
displayable_root = cls(root, parent=parent, is_last=is_last)
yield displayable_root

Expand All @@ -95,15 +119,27 @@ def make_tree(
count += 1

def __str__(self) -> str:
"""
The representation str via ``calling str()``.
:return:
"""
if self.parent is None:
return self.title

filename_prefix = self.FILE_LAST_PREFIX if self.is_last else self.FILE_MIDDLE_PREFIX
filename_prefix = self.LAST_PREFIX if self.is_last else self.MIDDLE_PREFIX

parts = [f"{filename_prefix} {self.title}"]

# if events := self.call.events:
# TODO!
# events_str = "\n".join([str(e) for e in events])

parent = self.parent
while parent and parent.parent is not None:
parts.append(self.PARENT_PREFIX_MIDDLE if parent.is_last else self.PARENT_PREFIX_LAST)
parent = parent.parent

return "".join(reversed(parts))

def __repr__(self) -> str:
return str(self)
8 changes: 7 additions & 1 deletion evm_trace/geth.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,15 @@ def _create_node(
elif frame.op.startswith("LOG") and len(frame.op) > 3 and frame.op[3].isnumeric():
num_topics = int(frame.op[3])
start_calldata_idx = -num_topics - 3

# TODO: Test this more.
data_key = frame.stack[start_calldata_idx]
data_idx = frame.memory.root.index(data_key) + 1
event_data = frame.memory.root[data_idx:]
event = Event(
data=event_data,
topics=[HexBytes(t) for t in frame.stack[start_calldata_idx:-4]],
selector=frame.stack[-num_topics],
calldata=HexBytes(b"".join(frame.stack[start_calldata_idx:-4])),
)
if "events" in node_kwargs:
node_kwargs["events"].append(event)
Expand Down

0 comments on commit 4f96bd1

Please sign in to comment.