|
|
|
@ -72,8 +72,6 @@ class LaserEVM: |
|
|
|
|
self.world_state = world_state |
|
|
|
|
self.open_states = [world_state] |
|
|
|
|
|
|
|
|
|
self.coverage = {} # type: Dict[str, Tuple[int, List[bool]]] |
|
|
|
|
|
|
|
|
|
self.total_states = 0 |
|
|
|
|
self.dynamic_loader = dynamic_loader |
|
|
|
|
|
|
|
|
@ -97,6 +95,10 @@ class LaserEVM: |
|
|
|
|
|
|
|
|
|
self._add_world_state_hooks = [] # type: List[Callable] |
|
|
|
|
self._execute_state_hooks = [] # type: List[Callable] |
|
|
|
|
|
|
|
|
|
self._start_sym_trans_hooks = [] # type: List[Callable] |
|
|
|
|
self._stop_sym_trans_hooks = [] # type: List[Callable] |
|
|
|
|
|
|
|
|
|
self._start_sym_exec_hooks = [] # type: List[Callable] |
|
|
|
|
self._stop_sym_exec_hooks = [] # type: List[Callable] |
|
|
|
|
|
|
|
|
@ -158,10 +160,6 @@ class LaserEVM: |
|
|
|
|
len(self.edges), |
|
|
|
|
self.total_states, |
|
|
|
|
) |
|
|
|
|
for code, coverage in self.coverage.items(): |
|
|
|
|
cov = sum(coverage[1]) / float(coverage[0]) * 100 |
|
|
|
|
|
|
|
|
|
log.info("Achieved {:.2f}% coverage for code: {}".format(cov, code)) |
|
|
|
|
|
|
|
|
|
if self.iprof is not None: |
|
|
|
|
log.info("Instruction Statistics:\n{}".format(self.iprof)) |
|
|
|
@ -170,42 +168,25 @@ class LaserEVM: |
|
|
|
|
hook() |
|
|
|
|
|
|
|
|
|
def _execute_transactions(self, address): |
|
|
|
|
"""This function executes multiple transactions on the address based on |
|
|
|
|
the coverage. |
|
|
|
|
"""This function executes multiple transactions on the address |
|
|
|
|
|
|
|
|
|
:param address: Address of the contract |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
self.coverage = {} |
|
|
|
|
for i in range(self.transaction_count): |
|
|
|
|
initial_coverage = self._get_covered_instructions() |
|
|
|
|
|
|
|
|
|
self.time = datetime.now() |
|
|
|
|
log.info( |
|
|
|
|
"Starting message call transaction, iteration: {}, {} initial states".format( |
|
|
|
|
i, len(self.open_states) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
for hook in self._start_sym_trans_hooks: |
|
|
|
|
hook() |
|
|
|
|
|
|
|
|
|
execute_message_call(self, address) |
|
|
|
|
|
|
|
|
|
end_coverage = self._get_covered_instructions() |
|
|
|
|
|
|
|
|
|
log.info( |
|
|
|
|
"Number of new instructions covered in tx %d: %d" |
|
|
|
|
% (i, end_coverage - initial_coverage) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
def _get_covered_instructions(self) -> int: |
|
|
|
|
"""Gets the total number of covered instructions for all accounts in |
|
|
|
|
the svm. |
|
|
|
|
|
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
total_covered_instructions = 0 |
|
|
|
|
for _, cv in self.coverage.items(): |
|
|
|
|
total_covered_instructions += sum(cv[1]) |
|
|
|
|
return total_covered_instructions |
|
|
|
|
for hook in self._stop_sym_trans_hooks: |
|
|
|
|
hook() |
|
|
|
|
|
|
|
|
|
def exec(self, create=False, track_gas=False) -> Union[List[GlobalState], None]: |
|
|
|
|
""" |
|
|
|
@ -284,7 +265,6 @@ class LaserEVM: |
|
|
|
|
|
|
|
|
|
self._execute_pre_hook(op_code, global_state) |
|
|
|
|
try: |
|
|
|
|
self._measure_coverage(global_state) |
|
|
|
|
new_global_states = Instruction( |
|
|
|
|
op_code, self.dynamic_loader, self.iprof |
|
|
|
|
).evaluate(global_state) |
|
|
|
@ -389,23 +369,6 @@ class LaserEVM: |
|
|
|
|
|
|
|
|
|
return new_global_states |
|
|
|
|
|
|
|
|
|
def _measure_coverage(self, global_state: GlobalState) -> None: |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
:param global_state: |
|
|
|
|
""" |
|
|
|
|
code = global_state.environment.code.bytecode |
|
|
|
|
number_of_instructions = len(global_state.environment.code.instruction_list) |
|
|
|
|
instruction_index = global_state.mstate.pc |
|
|
|
|
|
|
|
|
|
if code not in self.coverage.keys(): |
|
|
|
|
self.coverage[code] = ( |
|
|
|
|
number_of_instructions, |
|
|
|
|
[False] * number_of_instructions, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
self.coverage[code][1][instruction_index] = True |
|
|
|
|
|
|
|
|
|
def manage_cfg(self, opcode: str, new_states: List[GlobalState]) -> None: |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
@ -527,6 +490,10 @@ class LaserEVM: |
|
|
|
|
self._start_sym_exec_hooks.append(hook) |
|
|
|
|
elif hook_type == "stop_sym_exec": |
|
|
|
|
self._stop_sym_exec_hooks.append(hook) |
|
|
|
|
elif hook_type == "start_sym_trans": |
|
|
|
|
self._start_sym_trans_hooks.append(hook) |
|
|
|
|
elif hook_type == "stop_sym_trans": |
|
|
|
|
self._stop_sym_trans_hooks.append(hook) |
|
|
|
|
else: |
|
|
|
|
raise ValueError( |
|
|
|
|
"Invalid hook type %s. Must be one of {add_world_state}", hook_type |
|
|
|
|