Skip to content

Commit

Permalink
Apply eveem-org#16
Browse files Browse the repository at this point in the history
  • Loading branch information
palkeo committed May 8, 2020
1 parent f8a7275 commit 8859262
Showing 1 changed file with 54 additions and 52 deletions.
106 changes: 54 additions & 52 deletions pano/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ def handle_jumps(self, trace, line, condition):
trace.append(("jump", n))
return trace

if op == "jumpi":
elif op == "jumpi":
target = stack.pop()
if_condition = simplify_bool(stack.pop())

Expand Down Expand Up @@ -480,19 +480,7 @@ def handle_jumps(self, trace, line, condition):
logger.debug("jumpi -> if %s", trace[-1])
return trace

if op == "selfdestruct":
trace.append(("selfdestruct", stack.pop(),))
return trace

if op in ["stop", "assert_fail", "invalid"]:
trace.append((op,))
return trace

if op == "UNKNOWN":
trace.append(("invalid",))
return trace

if op in ["return", "revert"]:
elif op in ["return", "revert"]:
p = stack.pop()
n = stack.pop()

Expand All @@ -504,6 +492,18 @@ def handle_jumps(self, trace, line, condition):

return trace

elif op == "selfdestruct":
trace.append(("selfdestruct", stack.pop(),))
return trace

elif op in ["stop", "assert_fail", "invalid"]:
trace.append((op,))
return trace

elif op == "UNKNOWN":
trace.append(("invalid",))
return trace

return None

def apply_stack(self, ret, line):
Expand Down Expand Up @@ -538,16 +538,6 @@ def trace(exp, *format_args):
else:
trace("[{}] {} {}", line[0], C.asm(op), C.asm(str(line[2])))

assert op not in [
"jump",
"jumpi",
"revert",
"return",
"stop",
"jumpdest",
"UNKNOWN",
]

param = 0
if len(line) > 2:
param = line[2]
Expand All @@ -569,32 +559,53 @@ def trace(exp, *format_args):
]:
stack.append(arithmetic.eval((op, stack.pop(), stack.pop(),)))

if op in ["mulmod", "addmod"]:
stack.append(("mulmod", stack.pop(), stack.pop(), stack.pop()))
elif op[:4] == "push":
stack.append(param)

elif op == "pop":
stack.pop()

elif op == "dup":
stack.dup(param)

if op == "mul":
elif op == "mul":
stack.append(mul_op(stack.pop(), stack.pop()))

if op == "or":
elif op == "or":
stack.append(or_op(stack.pop(), stack.pop()))

if op == "shl":
elif op == "add":
stack.append(add_op(stack.pop(), stack.pop()))

elif op == "sub":
left = stack.pop()
right = stack.pop()

if type(left) == int and type(right) == int:
stack.append(arithmetic.sub(left, right))
else:
stack.append(sub_op(left, right))

elif op in ["mulmod", "addmod"]:
stack.append(("mulmod", stack.pop(), stack.pop(), stack.pop()))

elif op == "shl":
off = stack.pop()
exp = stack.pop()
if all_concrete(off, exp):
stack.append(exp << off)
else:
stack.append(mask_op(exp, shl=off))

if op == "shr":
elif op == "shr":
off = stack.pop()
exp = stack.pop()
if all_concrete(off, exp):
stack.append(exp >> off)
else:
stack.append(mask_op(exp, offset=minus_op(off), shr=off))

if op == "sar":
elif op == "sar":
off = stack.pop()
exp = stack.pop()
if all_concrete(off, exp):
Expand All @@ -613,18 +624,6 @@ def trace(exp, *format_args):
# FIXME: This won't give the right result...
stack.append(mask_op(exp, offset=minus_op(off), shr=off))

if op == "add":
stack.append(add_op(stack.pop(), stack.pop()))

if op == "sub":
left = stack.pop()
right = stack.pop()

if type(left) == int and type(right) == int:
stack.append(arithmetic.sub(left, right))
else:
stack.append(sub_op(left, right))

elif op in ["not", "iszero"]:
stack.append((op, stack.pop()))

Expand Down Expand Up @@ -883,18 +882,9 @@ def trace(exp, *format_args):

stack.append("create2.new_address")

elif op[:4] == "push":
stack.append(param)

elif op == "pc":
stack.append(line[0])

elif op == "pop":
stack.pop()

elif op == "dup":
stack.dup(param)

elif op == "msize":
self.counter += 1
vname = f"_{self.counter}"
Expand Down Expand Up @@ -922,6 +912,18 @@ def trace(exp, *format_args):
]:
stack.append(op)

else:
# TODO: Maybe raise an error directly?
assert op not in [
"jump",
"jumpi",
"revert",
"return",
"stop",
"jumpdest",
"UNKNOWN",
]

if stack.len() - previous_len != opcode_dict.stack_diffs[op]:
logger.error("line: %s", line)
logger.error("stack: %s", stack)
Expand Down

5 comments on commit 8859262

@ytrezq
Copy link

@ytrezq ytrezq commented on 8859262 May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice !
I didn’t add an option for tuning timeouts because I’m thinking about the nopython mode from the Numba python’s package (at least for the most intensive parts which would allows for automatic parallelization while removing the ɢɪʟ) where all external variables should be removed.

@palkeo
Copy link
Owner

@palkeo palkeo commented on 8859262 May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this fork I added a "--profile" option if you want to see what takes the most time. And in the contract I looked at, the main bottleneck is actually during postprocessing, and the make_whiles function.
But I personally don't mind too much about performance (and my rewrite by removing tilde actually made performance a bit worse).

@ytrezq
Copy link

@ytrezq ytrezq commented on 8859262 May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@palkeo thanks but python has the cProfile module.
I’d personally had keep the tide requirement.

You don’t care about performance because you don’t have to decompile contracts like this one or this one in full which is requiring 100Gb of ʀᴀᴍ and several weeks.

As you solved problems I couldn’t figure, I thought you’d be more experienced than me for the Numba rewrite (though once made compatible this is the matter of adding a function decorator).

@palkeo
Copy link
Owner

@palkeo palkeo commented on 8859262 May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the "--profile" I added uses cProfile: https://github.com/palkeo/panoramix/blob/master/panoramix.py#L109

I just decompiled 100% of the functions in 0x312a90b32bbfdd064f3b223a0ce5fe1ff44b44a8 in < 20 minutes and < 8 Gb of ram with my fork. So I'm not sure what you mean?
I do decompile all contracts of mainnet (see oko.palkeo.com), so I care about these edge cases, that's why I added stricter limits/timeouts in my fork.

By the way I sent you an email.

@palkeo
Copy link
Owner

@palkeo palkeo commented on 8859262 May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Anyway feel free to contact me if you want to talk directly outside of github: https://www.palkeo.com/en/about.html

Please sign in to comment.