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