Skip to content

Commit

Permalink
add evm trace commands
Browse files Browse the repository at this point in the history
  • Loading branch information
lmy375 committed Mar 30, 2024
1 parent 080cf39 commit 555b7bf
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 36 deletions.
45 changes: 45 additions & 0 deletions docs/cn/cmd_tx.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,49 @@ CALL 0xf977814e90da44bfa03b6295a0616a897441acec > 0xdac17f958d2ee523a22062069945
SSTORE [0x6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf] 0x00000000000000000000000000000000000000000000000000000000287a4ca8 <= 0x287a73b8
CALLER 0xf977814e90da44bfa03b6295a0616a897441acec
Event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef 3 topics 32 bytes data
```

## evm_trace_tx

打印交易 EVM trace。使用内置的简单 EVM 执行,执行过程不计算 gas,不支持 precompile 合约。交易将在实际发生的前一区块上模拟。因此输出结果可能与实际有所不同。

```
peth > evm_trace_tx 0x3e1dde3220f5a4cdda7a0190e0fe36952c893550e84256d003716f9cc49cd83b
[1-5370] SLOAD [0x0] => 0xc6cde7c39eb2f0f0095f41570af89efc2c1ea828
[1-5455] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000006 => e0226a13c41ea23f3e20affcdd11db85d3012a37825847eade8b1b20f198642d
[1-5459] SLOAD [0xe0226a13c41ea23f3e20affcdd11db85d3012a37825847eade8b1b20f198642d] => 0x0
[1-5487] SLOAD [0xa] => 0x0
[1-9922] SLOAD [0x3] => 0x0
[1-9956] SLOAD [0x4] => 0x0
[1-10057] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000002 => ea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2
[1-10058] SLOAD [0xea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2] => 0x51101b10
[1-10135] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000002 => ea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2
[1-10138] SSTORE 0xdAC17F958D2ee523a2206206994597C13D831ec7[105847515027243004738223111774324159193299488367755976363922685335240752777682] = 0x0
[1-10206] SHA3 0000000000000000000000009dfd543bc87a6e15d1fc126efdf201ac5cc8355c0000000000000000000000000000000000000000000000000000000000000002 => 10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f
[1-10207] SLOAD [0x10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f] => 0xb2a7bcc9325
[1-10284] SHA3 0000000000000000000000009dfd543bc87a6e15d1fc126efdf201ac5cc8355c0000000000000000000000000000000000000000000000000000000000000002 => 10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f
[1-10287] SSTORE 0xdAC17F958D2ee523a2206206994597C13D831ec7[7634139833736913371177489221108128263355955228192439644917754002988222782303] = 0xb2accdcae35
[1-10748] LOG3 log3 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,0x138dbff3ee829429ca4dc2a674cd2231ff8afc0b,0x9dfd543bc87a6e15d1fc126efdf201ac5cc8355c 0000000000000000000000000000000000000000000000000000000051101b10
```

## evm_trace_call

模拟执行指定的交易数据,并打印 EVM trace。
```
peth > evm_trace_call 0xdac17f958d2ee523a2206206994597c13d831ec7 0xa9059cbb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000002710 0xF977814e90dA44bFA03b6295A0616a897441aceC
[1-5370] SLOAD [0x0] => 0xc6cde7c39eb2f0f0095f41570af89efc2c1ea828
[1-5455] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000006 => daea8bd015a248c0934f48b5a4f6843891a74609aae5e9ab82e474bcb09dda52
[1-5459] SLOAD [0xdaea8bd015a248c0934f48b5a4f6843891a74609aae5e9ab82e474bcb09dda52] => 0x0
[1-5487] SLOAD [0xa] => 0x0
[1-9922] SLOAD [0x3] => 0x0
[1-9956] SLOAD [0x4] => 0x0
[1-10057] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000002 => 0be16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36
[1-10058] SLOAD [0xbe16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36] => 0xaa87bee538000
[1-10135] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000002 => 0be16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36
[1-10138] SSTORE 0xdac17f958d2ee523a2206206994597c13d831ec7[5373737276635141702492552203389591558520326902018227180554579176633808215862] = 0xaa87bee5358f0
[1-10206] SHA3 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000002 => 6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf
[1-10207] SLOAD [0x6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf] => 0x287a4ca8
[1-10284] SHA3 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000002 => 6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf
[1-10287] SSTORE 0xdac17f958d2ee523a2206206994597c13d831ec7[48013083170805714774496382090249254937812307080934975231686332112420340408239] = 0x287a73b8
[1-10748] LOG3 log3 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,0xf977814e90da44bfa03b6295a0616a897441acec,0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0000000000000000000000000000000000000000000000000000000000002710
```
49 changes: 49 additions & 0 deletions docs/en/cmd_tx.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,53 @@ CALL 0xf977814e90da44bfa03b6295a0616a897441acec > 0xdac17f958d2ee523a22062069945
SSTORE [0x6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf] 0x00000000000000000000000000000000000000000000000000000000287a4ca8 <= 0x287a73b8
CALLER 0xf977814e90da44bfa03b6295a0616a897441acec
Event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef 3 topics 32 bytes data
```

## evm_trace_tx

Simulate the transaction in a simple built-in EVM and print transaction trace.
Please note that the simulation results may differ from the actual results because:
1. This simple EVM does not measure gas.
2. It does not support precompile contracts.
3. The transaction will be simulated in the block prior to the one it is in.

```
peth > evm_trace_tx 0x3e1dde3220f5a4cdda7a0190e0fe36952c893550e84256d003716f9cc49cd83b
[1-5370] SLOAD [0x0] => 0xc6cde7c39eb2f0f0095f41570af89efc2c1ea828
[1-5455] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000006 => e0226a13c41ea23f3e20affcdd11db85d3012a37825847eade8b1b20f198642d
[1-5459] SLOAD [0xe0226a13c41ea23f3e20affcdd11db85d3012a37825847eade8b1b20f198642d] => 0x0
[1-5487] SLOAD [0xa] => 0x0
[1-9922] SLOAD [0x3] => 0x0
[1-9956] SLOAD [0x4] => 0x0
[1-10057] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000002 => ea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2
[1-10058] SLOAD [0xea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2] => 0x51101b10
[1-10135] SHA3 000000000000000000000000138dbff3ee829429ca4dc2a674cd2231ff8afc0b0000000000000000000000000000000000000000000000000000000000000002 => ea039209bd83a7f24ceccd7f0e5a5a94de49a961c5a963efbd1a6d088c2849d2
[1-10138] SSTORE 0xdAC17F958D2ee523a2206206994597C13D831ec7[105847515027243004738223111774324159193299488367755976363922685335240752777682] = 0x0
[1-10206] SHA3 0000000000000000000000009dfd543bc87a6e15d1fc126efdf201ac5cc8355c0000000000000000000000000000000000000000000000000000000000000002 => 10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f
[1-10207] SLOAD [0x10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f] => 0xb2a7bcc9325
[1-10284] SHA3 0000000000000000000000009dfd543bc87a6e15d1fc126efdf201ac5cc8355c0000000000000000000000000000000000000000000000000000000000000002 => 10e0c52043da30cfc95e2ab36b7a3a506c6e5c45884edf3a773e65cfcb4e1b5f
[1-10287] SSTORE 0xdAC17F958D2ee523a2206206994597C13D831ec7[7634139833736913371177489221108128263355955228192439644917754002988222782303] = 0xb2accdcae35
[1-10748] LOG3 log3 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,0x138dbff3ee829429ca4dc2a674cd2231ff8afc0b,0x9dfd543bc87a6e15d1fc126efdf201ac5cc8355c 0000000000000000000000000000000000000000000000000000000051101b10
```

## evm_trace_call

Simulate the transaction and print the EVM trace as `evm_trace_tx` does.
```
peth > evm_trace_call 0xdac17f958d2ee523a2206206994597c13d831ec7 0xa9059cbb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000002710 0xF977814e90dA44bFA03b6295A0616a897441aceC
[1-5370] SLOAD [0x0] => 0xc6cde7c39eb2f0f0095f41570af89efc2c1ea828
[1-5455] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000006 => daea8bd015a248c0934f48b5a4f6843891a74609aae5e9ab82e474bcb09dda52
[1-5459] SLOAD [0xdaea8bd015a248c0934f48b5a4f6843891a74609aae5e9ab82e474bcb09dda52] => 0x0
[1-5487] SLOAD [0xa] => 0x0
[1-9922] SLOAD [0x3] => 0x0
[1-9956] SLOAD [0x4] => 0x0
[1-10057] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000002 => 0be16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36
[1-10058] SLOAD [0xbe16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36] => 0xaa87bee538000
[1-10135] SHA3 000000000000000000000000f977814e90da44bfa03b6295a0616a897441acec0000000000000000000000000000000000000000000000000000000000000002 => 0be16d71963429204d70543701f859c43526c316ac005c10114f4694ca405f36
[1-10138] SSTORE 0xdac17f958d2ee523a2206206994597c13d831ec7[5373737276635141702492552203389591558520326902018227180554579176633808215862] = 0xaa87bee5358f0
[1-10206] SHA3 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000002 => 6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf
[1-10207] SLOAD [0x6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf] => 0x287a4ca8
[1-10284] SHA3 000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000002 => 6a26712a1b2f732f4c1fd85f9d6ed8235573aaa2a79aa2bab72c2423a73a9faf
[1-10287] SSTORE 0xdac17f958d2ee523a2206206994597c13d831ec7[48013083170805714774496382090249254937812307080934975231686332112420340408239] = 0x287a73b8
[1-10748] LOG3 log3 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,0xf977814e90da44bfa03b6295a0616a897441acec,0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 0000000000000000000000000000000000000000000000000000000000002710
```
77 changes: 57 additions & 20 deletions peth/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from peth.core.tracer import GethTracer, TxTrace
from peth.eth.abi import ABI, ABIFunction
from peth.eth.bytecode import Code
from peth.eth.evm import VM, Chain, ForkChain, Transaction
from peth.eth.sigs import Signature
from peth.eth.utils import (
CoinPrice,
Expand Down Expand Up @@ -553,10 +554,7 @@ def do_abi_decode(self, arg):
##################################################################
# Basic ETH commands.

def do_eth_call(self, arg):
"""
eth_call <to> <calldata> [<sender>] [<value>]
"""
def _parse_tx_call_args(self, arg):
args = arg.split()

to = args[0]
Expand All @@ -570,7 +568,15 @@ def do_eth_call(self, arg):
if len(args) >= 4:
value = args[4]
else:
value = "0x0"
value = 0

return to, data, sender, value

def do_eth_call(self, arg):
"""
eth_call <to> <calldata> [<sender>] [<value>]
"""
to, data, sender, value = self._parse_tx_call_args(arg)

try:
ret = self.web3.eth.call(
Expand Down Expand Up @@ -1580,22 +1586,9 @@ def do_trace_tx(self, arg):

def do_trace_call(self, arg):
"""
trace_call <to> <calldata> [<sender>] [<value>]: Perform a call and print trace. Note: A Debug RPC is required.
trace_call <to> <calldata> [<sender>] [<value>]: Perform a call and print trace. Note: A Debug RPC is required.
"""
args = arg.split()

to = args[0]
data = args[1]

if len(args) >= 3:
sender = args[2]
else:
sender = self.peth.sender

if len(args) >= 4:
value = args[4]
else:
value = "0x0"
to, data, sender, value = self._parse_tx_call_args(arg)

js = "legacy_tracer.js"
tracer = GethTracer(self.peth.rpc_url, js)
Expand All @@ -1605,6 +1598,50 @@ def do_trace_call(self, arg):
trace = TxTrace(self.peth.chain, result)
trace.print()

def do_evm_trace_tx(self, arg):
"""
evm_trace_tx <txid>:
Simulate the transaction in a simple built-in EVM and print transaction trace.
Please note that the simulation results may differ from the actual results because:
1. This simple EVM does not measure gas.
2. It does not support precompile contracts.
3. The transaction will be simulated in the block prior to the one it is in.
"""
txid = arg.strip()
tx = self.web3.eth.get_transaction(txid)
block_number = tx["blockNumber"] - 1

# Chain.debug = True
# VM.debug = True
VM.trace = True

chain = Chain(ForkChain(self.web3, block_number))
# ins = Inspector(chain, self.peth)
r = chain.apply_transaction(
Transaction(
sender=tx["from"],
to=tx["to"],
value=tx["value"],
data=HexBytes(tx["input"]),
)
)
# ins.print_call_trace()
r.trace.print()

def do_evm_trace_call(self, arg):
"""
evm_trace_call <to> <calldata> [<sender>] [<value>]:
Simulate the transaction in a simple built-in EVM and print transaction trace.
"""
to, data, sender, value = self._parse_tx_call_args(arg)
VM.trace = True

chain = Chain(ForkChain(self.web3))
r = chain.apply_transaction(
Transaction(sender=sender, to=to, value=value, data=HexBytes(data))
)
r.trace.print()

##################################################################
# Bytecode tools.

Expand Down
19 changes: 19 additions & 0 deletions peth/eth/evm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from .chain import Chain
from .contract import Contract
from .forkchain import ForkChain
from .inspector import Inspector
from .receipt import Receipt
from .trace import Trace
from .transaction import Transaction
from .vm import VM

__all__ = [
"Chain",
"Contract",
"ForkChain",
"Trace",
"Transaction",
"Receipt",
"VM",
"Inspector",
]
2 changes: 1 addition & 1 deletion peth/eth/evm/forkchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, web3, fix_block_number: int = 0) -> None:
self.fix_block_number = web3.eth.block_number # Fix to current.

self.chainid = web3.eth.chain_id
self.block = web3.eth.get_block(self.fix_block_number)
self.block = web3.eth.get_block(self.fix_block_number - 1)

if not os.path.exists(config.EVM_OUTPUT_PATH):
os.makedirs(config.EVM_OUTPUT_PATH)
Expand Down
12 changes: 5 additions & 7 deletions peth/eth/evm/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

class Inspector(object):

def __init__(self, chain=None) -> None:
def __init__(self, chain, peth) -> None:
super().__init__()

# Including Trasactions and Receipts.
Expand All @@ -18,15 +18,13 @@ def __init__(self, chain=None) -> None:
self.created_contracts = set()
self.erc20_contracts = set()

if chain:
self.attach_chain(chain)
self.peth = peth
self.attach_chain(chain)

def attach_chain(self, chain):
self.chain = chain
self.chain.inspector = self

# TODO: self.peth = peth.get_or_create(chain.chain_id)

def detach(self):
if self.chain:
self.chain.inspector = None
Expand All @@ -44,7 +42,7 @@ def get_address_name(self, addr, with_address=True):
else:
return name

return hex(addr)
return addr

def add_transaction(self, tx: Transaction):
self._tx_traces.append(tx)
Expand Down Expand Up @@ -82,7 +80,7 @@ def gen_relation_graph(self, file=None):
# for: http://relation-graph.com/#/options-tools

def node_id(addr):
return hex(addr)
return addr

def node_text(addr):
return self.get_address_name(addr, False) # short
Expand Down
17 changes: 16 additions & 1 deletion peth/eth/evm/trace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
from typing import List, Optional

from ..opcodes import OpCode


class Step(object):
def __init__(
Expand All @@ -22,6 +24,14 @@ def __str__(self):
stack = ",".join(hex(i) for i in self.stack[::-1]) # reverse.
return "%-10s %-20s %-100s %-10s" % (depth_pc, self.op, self.msg, stack)

def print(self, full=False):
depth_pc = f"[{self.depth}-{self.pc}]"
s = "%-10s %-20s %-100s" % (depth_pc, self.op, self.msg)
if full:
stack = ",".join(hex(i) for i in self.stack[::-1])
s += " %-10s" % stack
print(s)

@classmethod
def fromJSON(cls, d):
pc = d["pc"]
Expand All @@ -48,7 +58,7 @@ def same_as(self, other: "Step", check_stack=True) -> bool:

class Trace(object):
def __init__(self) -> None:
self.steps = []
self.steps: List[Step] = []

def pre_trace(
self, pc: int, op: int, depth: int, stack: List[int], msg: Optional[str] = None
Expand Down Expand Up @@ -134,3 +144,8 @@ def compare_debug_trace_transaction(
other.steps.append(Step.fromJSON(d))

return self.compare(other, outputfile)

def print(self, level=2):
for step in self.steps:
if OpCode.from_mnemonic(step.op).print_level <= level:
step.print()
Loading

0 comments on commit 555b7bf

Please sign in to comment.