Skip to content

Commit

Permalink
eth/tracer:compare opcode in CaptureState
Browse files Browse the repository at this point in the history
  • Loading branch information
JukLee0ira committed Oct 24, 2024
1 parent 14ef21a commit bd33b76
Showing 1 changed file with 18 additions and 42 deletions.
60 changes: 18 additions & 42 deletions eth/tracers/native/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ func init() {
}

type contractTracer struct {
Addrs map[string]string
Addrs []string
config contractTracerConfig
interrupt uint32 // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
}

type contractTracerConfig struct {
OpCode string `json:"opCode"` // Target opcode to trace
WithByteCode bool `json:"withByteCode"` // If true, bytecode will be collected
OpCode string `json:"opCode"` // Target opcode to trace
}

// NewContractTracer returns a native go tracer which tracks the contracr was created
Expand All @@ -53,7 +52,7 @@ func NewContractTracer(cfg json.RawMessage) (tracers.Tracer, error) {
}
}
t := &contractTracer{
Addrs: make(map[string]string, 1),
Addrs: make([]string, 1),
config: config,
}
// handle invalid opcode case
Expand All @@ -66,31 +65,36 @@ func NewContractTracer(cfg json.RawMessage) (tracers.Tracer, error) {
}

func (t *contractTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
if create {
validateAndStoreOpCode(t, input, to)
if create || t.config.OpCode == "CALL" {
t.Addrs = append(t.Addrs, addrToHex(to))
}
}

func (t *contractTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
}

func (t *contractTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
}

func (t *contractTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
}

func (t *contractTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
// Skip if tracing was interrupted
if atomic.LoadUint32(&t.interrupt) > 0 {
// TODO: env.Cancel()
return
}
if typ == vm.CREATE || typ == vm.CREATE2 {
validateAndStoreOpCode(t, input, to)
// If the OpCode is empty , exit early.
if t.config.OpCode == "" {
return
}
if op.String() == t.config.OpCode {
addr := scope.Contract.Address()
t.Addrs = append(t.Addrs, addrToHex(addr))
}
}

func (t *contractTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
}

func (t *contractTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
}

func (t *contractTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
}

Expand All @@ -106,31 +110,3 @@ func (t *contractTracer) Stop(err error) {
t.reason = err
atomic.StoreUint32(&t.interrupt, 1)
}

func validateAndStoreOpCode(t *contractTracer, input []byte, to common.Address) {
// If the OpCode is not empty and doesn't match the input, exit early.
if t.config.OpCode != "" && !findOpcodes(input, vm.StringToOp(t.config.OpCode)) {
return
}
// If WithByteCode is true, store the input in the address mapping as hex.
if t.config.WithByteCode {
t.Addrs[addrToHex(to)] = bytesToHex(input)
} else {
t.Addrs[addrToHex(to)] = ""
}
}

// Compare bytecode with the given opcode, skipping PUSH instructions.
func findOpcodes(bytecode []byte, opcode vm.OpCode) bool {
for i := 0; i < len(bytecode); {
op := vm.OpCode(bytecode[i])
// Skip PUSH opcodes and their arguments
if op.IsPush() {
i += int(op - 95) // Directly calculate the number of bytes to skip
} else if op == opcode {
return true
}
i++
}
return false
}

0 comments on commit bd33b76

Please sign in to comment.