from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.plugins.plugin import LaserPlugin
from mythril.laser.ethereum.state.global_state import GlobalState


class InstructionCoveragePlugin(LaserPlugin):
    """InstructionCoveragePlugin

    This plugin measures the instruction coverage of mythril.
    The instruction coverage is the ratio between the instructions that have been executed
    and the total amount of instructions.

    Note that with lazy constraint solving enabled that this metric will be "unsound" as
    reachability will not be considered for the calculation of instruction coverage.

    """

    def initialize(self, symbolic_vm: LaserEVM):
        """Initializes the instruction coverage plugin

        Introduces hooks for each instruction
        :param symbolic_vm:
        :return:
        """
        pass

@@ -170,16 +170,67 @@
 lState%0A%0A
+import logging%0A%0Alog = logging.getLogger(__name__)%0A%0A
 %0Aclass I
@@ -902,9 +902,904 @@
     
-pass
+coverage = %7B%7D%0A%0A        @symbolic_vm.laser_hook(%22stop_sym_exec%22)%0A        def stop_sym_exec_hook():%0A            # Print results%0A            for code, code_cov in coverage.items():%0A                cov_percentage = sum(code_cov%5B1%5D) / float(code_cov%5B0%5D) * 100%0A%0A                log.info(%22Achieved %7B:.2f%7D%25 coverage for code: %7B%7D%22.format(cov_percentage, code))%0A%0A        @symbolic_vm.laser_hook(%22execute_state%22)%0A        def execute_state_hook(global_state: GlobalState):%0A            # Record coverage%0A            code = global_state.environment.code.bytecode%0A%0A            if code not in coverage.keys():%0A                number_of_instructions = len(global_state.environment.code.instruction_list)%0A                coverage%5Bcode%5D = (%0A                    number_of_instructions,%0A                    %5BFalse%5D * number_of_instructions,%0A                )%0A%0A            coverage%5Bcode%5D%5B1%5D%5Bglobal_state.mstate.pc%5D = True
 %0A

implement hooks for instruction coverage