arnaucube
arnaucube/evm-rsPublic Self-hosted repository
evm-rs/src/lib.rs
src/lib.rsRaw
  1#![allow(dead_code)]
  2
  3use num_bigint::BigUint;
  4use std::collections::HashMap;
  5pub mod opcodes;
  6pub mod u256;
  7
  8#[derive(Default)]
  9pub struct Stack {
 10    pub pc: usize,
 11    pub calldata_i: usize,
 12    pub calldata_size: usize,
 13    pub stack: Vec<[u8; 32]>,
 14    pub storage: HashMap<[u8; 32], Vec<u8>>,
 15    pub mem: Vec<u8>,
 16    pub gas: u64,
 17    pub opcodes: HashMap<u8, opcodes::Opcode>,
 18}
 19
 20impl Stack {
 21    pub fn new() -> Stack {
 22        let mut s = Stack {
 23            pc: 0,
 24            calldata_i: 0,
 25            calldata_size: 32,
 26            stack: Vec::new(),
 27            storage: HashMap::new(),
 28            mem: Vec::new(),
 29            gas: 10000000000,
 30            opcodes: HashMap::new(),
 31        };
 32        s.opcodes = opcodes::new_opcodes();
 33        s
 34    }
 35    pub fn print_stack(&self) {
 36        println!("stack ({}):", self.stack.len());
 37        for i in (0..self.stack.len()).rev() {
 38            // println!("{:x}", &self.stack[i][28..]);
 39            println!("{:?}", vec_u8_to_hex(self.stack[i].to_vec()));
 40        }
 41    }
 42    pub fn print_memory(&self) {
 43        if !self.mem.is_empty() {
 44            println!("memory ({}):", self.mem.len());
 45            println!("{:?}", vec_u8_to_hex(self.mem.to_vec()));
 46        }
 47    }
 48    pub fn print_storage(&self) {
 49        if !self.storage.is_empty() {
 50            println!("storage ({}):", self.storage.len());
 51            for (key, value) in self.storage.iter() {
 52                println!(
 53                    "{:?}: {:?}",
 54                    vec_u8_to_hex(key.to_vec()),
 55                    vec_u8_to_hex(value.to_vec())
 56                );
 57            }
 58        }
 59    }
 60    pub fn push(&mut self, b: [u8; 32]) {
 61        self.stack.push(b);
 62    }
 63    // push_arbitrary performs a push, but first converting the arbitrary-length
 64    // input into a 32 byte array
 65    pub fn push_arbitrary(&mut self, b: &[u8]) {
 66        // TODO if b.len()>32 return error
 67        let mut d: [u8; 32] = [0; 32];
 68        d[32 - b.len()..].copy_from_slice(b);
 69        self.stack.push(d);
 70    }
 71    // put_arbitrary puts in the last element of the stack the value
 72    pub fn put_arbitrary(&mut self, b: &[u8]) {
 73        // TODO if b.len()>32 return error
 74        let mut d: [u8; 32] = [0; 32];
 75        d[0..b.len()].copy_from_slice(b); // put without left padding
 76        let l = self.stack.len();
 77        self.stack[l - 1] = d;
 78    }
 79    pub fn pop(&mut self) -> Result<[u8; 32], String> {
 80        match self.stack.pop() {
 81            Some(x) => Ok(x),
 82            None => Err("pop err".to_string()), // WIP
 83        }
 84    }
 85    pub fn substract_gas(&mut self, val: u64) -> Result<(), String> {
 86        if self.gas < val {
 87            return Err("out of gas".to_string());
 88        }
 89        self.gas -= val;
 90        Ok(())
 91    }
 92
 93    pub fn execute(
 94        &mut self,
 95        code: &[u8],
 96        calldata: &[u8],
 97        debug: bool,
 98    ) -> Result<Vec<u8>, String> {
 99        self.pc = 0;
100        self.calldata_i = 0;
101        let l = code.len();
102
103        while self.pc < l {
104            let opcode = code[self.pc];
105            if !self.opcodes.contains_key(&opcode) {
106                return Err(format!("invalid opcode {:x}", opcode));
107            }
108
109            if debug {
110                println!(
111                    "{} (0x{:x}): pc={:?} gas={:?}",
112                    self.opcodes.get(&opcode).unwrap().name,
113                    opcode,
114                    self.pc,
115                    self.gas,
116                );
117                self.print_stack();
118                self.print_memory();
119                self.print_storage();
120                println!();
121            }
122            match opcode & 0xf0 {
123                0x00 => {
124                    // arithmetic
125                    match opcode {
126                        0x00 => {
127                            println!("0x00: STOP");
128                            return Ok(Vec::new());
129                        }
130                        0x01 => self.add()?,
131                        0x02 => self.mul()?,
132                        0x03 => self.sub()?,
133                        0x04 => self.div()?,
134                        0x05 => self.sdiv()?,
135                        0x06 => self.modulus()?,
136                        0x07 => self.smod()?,
137                        0x08 => self.add_mod()?,
138                        0x09 => self.mul_mod()?,
139                        0x0a => self.exp()?,
140                        // 0x0b => self.sign_extend(),
141                        _ => return Err(format!("unimplemented {:x}", opcode)),
142                    }
143                    self.pc += 1;
144                }
145                0x30 => {
146                    match opcode {
147                        0x35 => self.calldata_load(&calldata),
148                        0x36 => self.calldata_size(&calldata),
149                        0x39 => self.code_copy(&code)?,
150                        _ => return Err(format!("unimplemented {:x}", opcode)),
151                    }
152                    self.pc += 1;
153                }
154                0x50 => {
155                    self.pc += 1;
156                    match opcode {
157                        0x51 => self.mload()?,
158                        0x52 => self.mstore()?,
159                        0x55 => self.sstore()?,
160                        0x56 => self.jump(code)?,
161                        0x57 => self.jump_i(code)?,
162                        0x5b => self.jump_dest()?,
163                        _ => return Err(format!("unimplemented {:x}", opcode)),
164                    }
165                }
166                0x60 | 0x70 => {
167                    // push
168                    let n = (opcode - 0x5f) as usize;
169                    self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
170                    self.pc += 1 + n;
171                }
172                0x80 => {
173                    // 0x8x dup
174                    let l = self.stack.len();
175                    if opcode > 0x7f {
176                        self.stack.push(self.stack[l - (opcode - 0x7f) as usize]);
177                    } else {
178                        self.stack.push(self.stack[(0x7f - opcode) as usize]);
179                    }
180                    self.pc += 1;
181                }
182                0x90 => {
183                    // 0x9x swap
184                    let l = self.stack.len();
185                    let pos;
186                    if opcode > 0x8e {
187                        pos = l - (opcode - 0x8e) as usize;
188                    } else {
189                        pos = (0x8e - opcode) as usize;
190                    }
191                    self.stack.swap(pos, l - 1);
192                    self.pc += 1;
193                }
194                0xf0 => {
195                    if opcode == 0xf3 {
196                        let pos_to_return = u256::u256_to_u64(self.pop()?) as usize;
197                        let len_to_return = u256::u256_to_u64(self.pop()?) as usize;
198                        return Ok(self.mem[pos_to_return..pos_to_return + len_to_return].to_vec());
199                    }
200                }
201                _ => {
202                    return Err(format!("unimplemented {:x}", opcode));
203                }
204            }
205            self.substract_gas(self.opcodes.get(&opcode).unwrap().gas)?;
206        }
207        Ok(Vec::new())
208    }
209}
210pub fn vec_u8_to_hex(bytes: Vec<u8>) -> String {
211    let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
212    strs.join("")
213}