<commit_before>use utils::bigint::M256;
use utils::gas::Gas;
use utils::address::Address;

use super::{Memory, VectorMemory, Stack, VectorStack, PC, VectorPC, Result, Error};
use blockchain::{Block, FakeVectorBlock};
use transaction::{Transaction, VectorTransaction};

use std::borrow::BorrowMut;
use std::marker::PhantomData;

pub trait Machine {
    type P: PC;
    type M: Memory;
    type Sta: Stack;
    type T: Transaction;
    type B: Block;
    type Sub: Machine;

    fn pc(&self) -> &Self::P;
    fn pc_mut(&mut self) -> &mut Self::P;
    fn memory(&self) -> &Self::M;
    fn memory_mut(&mut self) -> &mut Self::M;
    fn stack(&self) -> &Self::Sta;
    fn stack_mut(&mut self) -> &mut Self::Sta;

    fn transaction(&self) -> &Self::T;
    fn block(&self) -> &Self::B;
    fn block_mut(&mut self) -> &mut Self::B;

    fn use_gas(&mut self, gas: Gas);
    fn used_gas(&self) -> Gas;
    fn return_values(&self) -> &[u8];
    fn set_return_values(&mut self, data: &[u8]);

    fn fork<F: FnOnce(&mut Self::Sub)>(&mut self, gas: Gas, from:
                                       Address, to: Address, value: M256,
                                       memory_in_start: M256,
                                       memory_in_len: M256,
                                       memory_out_start: M256,
                                       memory_out_len: M256, f: F);

    fn step(&mut self) -> Result<()> where Self: Sized {
        if self.pc().stopped() {
            return Err(Error::Stopped)
        }

        if !self.available_gas().is_valid() {
            return Err(Error::EmptyGas)
        }

        let opcode = self.pc_mut().peek_opcode()?;
        let before = opcode.gas_cost_before(self)?;
        opcode.run(self)?;
        let after = opcode.gas_cost_after(self);

        self.pc_mut().read_opcode().unwrap();
        self.use_gas(before);
        self.use_gas(after);

        Ok(())
    }

    fn fire(&mut self) -> Result<()> where Self: Sized {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {<commit_msg>Problem: the restore logic is incorrect Solution: replace ? with the correct restore logic<commit_after>use utils::bigint::M256;
use utils::gas::Gas;
use utils::address::Address;

use super::{Memory, VectorMemory, Stack, VectorStack, PC, VectorPC, Result, Error};
use blockchain::{Block, FakeVectorBlock};
use transaction::{Transaction, VectorTransaction};

use std::borrow::BorrowMut;
use std::marker::PhantomData;

pub trait Machine {
    type P: PC;
    type M: Memory;
    type Sta: Stack;
    type T: Transaction;
    type B: Block;
    type Sub: Machine;

    fn pc(&self) -> &Self::P;
    fn pc_mut(&mut self) -> &mut Self::P;
    fn memory(&self) -> &Self::M;
    fn memory_mut(&mut self) -> &mut Self::M;
    fn stack(&self) -> &Self::Sta;
    fn stack_mut(&mut self) -> &mut Self::Sta;

    fn transaction(&self) -> &Self::T;
    fn block(&self) -> &Self::B;
    fn block_mut(&mut self) -> &mut Self::B;

    fn use_gas(&mut self, gas: Gas);
    fn used_gas(&self) -> Gas;
    fn return_values(&self) -> &[u8];
    fn set_return_values(&mut self, data: &[u8]);

    fn fork<F: FnOnce(&mut Self::Sub)>(&mut self, gas: Gas, from:
                                       Address, to: Address, value: M256,
                                       memory_in_start: M256,
                                       memory_in_len: M256,
                                       memory_out_start: M256,
                                       memory_out_len: M256, f: F);

    fn step(&mut self) -> Result<()> where Self: Sized {
        if self.pc().stopped() {
            return Err(Error::Stopped)
        }

        if !self.available_gas().is_valid() {
            return Err(Error::EmptyGas)
        }

        let position = self.pc().position();
        let restore = |machine: &mut Self| { machine.pc_mut().jump(position); };

        let opcode = match self.pc_mut().read_opcode() {
            Ok(opcode) => opcode,
            Err(e) => {
                restore(self);
                return Err(e);
            }
        };
        let before = match opcode.gas_cost_before(self) {
            Ok(gas) => gas,
            Err(e) => {
                restore(self);
                return Err(e);
            }
        };
        match opcode.run(self) {
            Ok(()) => (),
            Err(e) => {
                restore(self);
                return Err(e);
            }
        };
        let after = opcode.gas_cost_after(self);

        self.use_gas(before);
        self.use_gas(after);

        Ok(())
    }

    fn fire(&mut self) -> Result<()> where Self: Sized {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {
{'fraction_non_alphanumeric': 0.1466033450340698, 'fraction_numerical': 0.008259343382201115, 'mean_word_length': 1.8747774480712167, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7415858', 'n_tokens_mistral': 1540, 'n_tokens_neox': 1481, 'n_words': 368}