mirror of https://github.com/ConsenSys/mythril
Add the first code to build transaction traces from the storage state at STOP instruction and a combination strategy to build felxibly large trace chain combinations. Starting from the trace of a constructor and using the traces of the external and public functions of a contract. All possible programmstates to a certain depth can be reached.
parent
c3131a579d
commit
0f458e7541
@ -0,0 +1,22 @@ |
||||
from mythril.analysis.report import Issue |
||||
import logging |
||||
|
||||
|
||||
''' |
||||
Build execution traces from the statespace |
||||
''' |
||||
|
||||
def print_obj(obj): |
||||
print() |
||||
print(obj) |
||||
# print(dir(obj)) |
||||
print() |
||||
|
||||
|
||||
def execute(statespace): |
||||
|
||||
logging.debug("Executing module: Transaction End") |
||||
|
||||
traces = [] |
||||
|
||||
return [] |
@ -0,0 +1,27 @@ |
||||
import logging |
||||
from mythril.solidnotary.transactiontrace import TransactionTrace |
||||
|
||||
class SolidNotary: |
||||
|
||||
def __init__(self): |
||||
# Todo Parse Annotations and store them in an additional structure |
||||
# Todo receive a list of files or a file, these are modified for the analysis |
||||
pass |
||||
|
||||
def notarize(self): |
||||
# Todo Instantiate an instance of Mythril, analyze and print the result |
||||
# Todo Find how they are storing results |
||||
pass |
||||
|
||||
def get_transaction_traces(statespace): |
||||
logging.debug("Executing module: Transaction End") |
||||
|
||||
traces = [] |
||||
|
||||
for k in statespace.nodes: |
||||
node = statespace.nodes[k] |
||||
for state in node.states: |
||||
instruction = state.get_current_instruction() |
||||
if instruction['opcode'] == "STOP": |
||||
traces.append(TransactionTrace(state.environment.active_account.storage)) |
||||
return traces |
@ -0,0 +1,54 @@ |
||||
class TransactionTrace: |
||||
|
||||
def __init__(self, storage): |
||||
self.storage = storage |
||||
# Todo Identifiy addional trace information such as blocknumber and more |
||||
|
||||
""" |
||||
Applies the new trace tt on a possibly even changed trace self. |
||||
""" |
||||
def apply_trace(self, tt): |
||||
if tt is None: |
||||
return self |
||||
# Todo implement application of a trace on a existing trace. |
||||
return None |
||||
|
||||
def apply_traces_parallel(self, traces): |
||||
combined_traces = [] |
||||
for trace in traces: |
||||
combined_traces.append(self.apply_trace(trace)) |
||||
return combined_traces |
||||
|
||||
def apply_exact_trace_levels(self, traces, depth): |
||||
# Todo maybe some faster trace build not building one level at a time to e.g. |
||||
# Todo reach level 17 but build 2, then 4, then 8 and then 16 then 17 |
||||
trace_lvl_n = [self] |
||||
for i in range(depth): |
||||
trace_lvl_np1 = [] |
||||
for trace in trace_lvl_n: |
||||
trace_lvl_np1.append(trace.apply_traces_parallel(traces)) |
||||
if deep_equals(trace_lvl_np1, trace_lvl_n): # Fixpoint detected, function needs to ignore lists, dicts and objects. |
||||
return trace_lvl_n |
||||
trace_lvl_n = trace_lvl_np1 |
||||
return trace_lvl_n |
||||
|
||||
def apply_up_to_trace_levels(self, traces, depth): |
||||
traces_up_to = [[self]] # elements are trace_levels |
||||
for i in range(depth): |
||||
trace_lvl_np1 = [] |
||||
for trace in traces_up_to[-1]: |
||||
trace_lvl_np1.append(trace.apply_traces_parallel(traces)) |
||||
for trace_lvl_i in traces_up_to: |
||||
# the following might be faster to check when using a content representing hash |
||||
if deep_equals(trace_lvl_np1, trace_lvl_i): # cycle in the traces of trace chains detected: levels |
||||
# while repeat themselves, function needs to ignore lists, dicts and objects. |
||||
return traces_up_to |
||||
traces_up_to.append(trace_lvl_np1) |
||||
return traces_up_to |
||||
|
||||
""" |
||||
Either do only deep checing here and use the proper trace or storage_slot reduction in the apply function. Or do |
||||
both here. |
||||
""" |
||||
def deep_equals(trace_lvl1, trace_lvl2): |
||||
pass |
Loading…
Reference in new issue