fuel-vm 0.2.0

FuelVM interpreter.
Documentation
use super::Interpreter;
use crate::consts::{MEM_MAX_ACCESS_SIZE, VM_MAX_RAM};
use crate::crypto;
use crate::error::RuntimeError;

use fuel_asm::PanicReason;
use fuel_tx::crypto::Hasher;
use fuel_types::{Bytes32, Bytes64, Word};

impl<S> Interpreter<S> {
    pub(crate) fn ecrecover(&mut self, a: Word, b: Word, c: Word) -> Result<(), RuntimeError> {
        if a > VM_MAX_RAM - Bytes64::LEN as Word
            || b > VM_MAX_RAM - Bytes64::LEN as Word
            || c > VM_MAX_RAM - Bytes32::LEN as Word
        {
            return Err(PanicReason::MemoryOverflow.into());
        }

        let (a, b, c) = (a as usize, b as usize, c as usize);

        let bx = b + Bytes64::LEN;
        let cx = c + Bytes32::LEN;

        let e = &self.memory[c..cx];
        let sig = &self.memory[b..bx];

        match crypto::secp256k1_sign_compact_recover(sig, e) {
            Ok(pk) => {
                self.try_mem_write(a, pk.as_ref())?;
                self.clear_err();
            }

            Err(_) => {
                self.try_zeroize(a, Bytes64::LEN)?;
                self.set_err();
            }
        }

        self.inc_pc()
    }

    pub(crate) fn keccak256(&mut self, a: Word, b: Word, c: Word) -> Result<(), RuntimeError> {
        use sha3::{Digest, Keccak256};

        if a > VM_MAX_RAM - Bytes32::LEN as Word || c > MEM_MAX_ACCESS_SIZE || b > VM_MAX_RAM - c {
            return Err(PanicReason::MemoryOverflow.into());
        }

        let (a, b, c) = (a as usize, b as usize, c as usize);
        let bc = b + c;

        let mut h = Keccak256::new();

        h.update(&self.memory[b..bc]);

        self.try_mem_write(a, h.finalize().as_slice())?;

        self.inc_pc()
    }

    pub(crate) fn sha256(&mut self, a: Word, b: Word, c: Word) -> Result<(), RuntimeError> {
        if a > VM_MAX_RAM - Bytes32::LEN as Word || c > MEM_MAX_ACCESS_SIZE || b > VM_MAX_RAM - c {
            return Err(PanicReason::MemoryOverflow.into());
        }

        let (a, b, c) = (a as usize, b as usize, c as usize);
        let bc = b + c;

        self.try_mem_write(a, Hasher::hash(&self.memory[b..bc]).as_ref())?;

        self.inc_pc()
    }
}