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;
  6
  7#[derive(Default)]
  8pub struct Stack {
  9    pub pc: usize,
 10    pub calldata_i: usize,
 11    pub stack: Vec<[u8; 32]>,
 12    pub mem: Vec<u8>,
 13    pub gas: u64,
 14    pub opcodes: HashMap<u8, opcodes::Opcode>,
 15}
 16
 17impl Stack {
 18    pub fn new() -> Stack {
 19        let mut s = Stack {
 20            pc: 0,
 21            calldata_i: 0,
 22            stack: Vec::new(),
 23            mem: Vec::new(),
 24            gas: 10000000000,
 25            opcodes: HashMap::new(),
 26        };
 27        s.opcodes = opcodes::new_opcodes();
 28        s
 29    }
 30    pub fn print_stack(&self) {
 31        for i in (0..self.stack.len()).rev() {
 32            println!("{:x?}", &self.stack[i][28..]);
 33        }
 34    }
 35    pub fn push(&mut self, b: [u8; 32]) {
 36        self.stack.push(b);
 37    }
 38    // push_arbitrary performs a push, but first converting the arbitrary-length
 39    // input into a 32 byte array
 40    pub fn push_arbitrary(&mut self, b: &[u8]) {
 41        // TODO if b.len()>32 return error
 42        let mut d: [u8; 32] = [0; 32];
 43        d[32 - b.len()..].copy_from_slice(b);
 44        self.stack.push(d);
 45    }
 46    // put_arbitrary puts in the last element of the stack the value
 47    pub fn put_arbitrary(&mut self, b: &[u8]) {
 48        // TODO if b.len()>32 return error
 49        let mut d: [u8; 32] = [0; 32];
 50        d[32 - b.len()..].copy_from_slice(b);
 51        let l = self.stack.len();
 52        self.stack[l - 1] = d;
 53    }
 54    pub fn pop(&mut self) -> [u8; 32] {
 55        match self.stack.pop() {
 56            Some(x) => x,
 57            None => panic!("err"),
 58        }
 59    }
 60
 61    pub fn execute(&mut self, code: &[u8], calldata: &[u8], debug: bool) -> Vec<u8> {
 62        self.pc = 0;
 63        self.calldata_i = 0;
 64        let l = code.len();
 65
 66        while self.pc < l {
 67            let opcode = code[self.pc];
 68            if !self.opcodes.contains_key(&opcode) {
 69                panic!("invalid opcode {:x}", opcode);
 70            }
 71
 72            if debug {
 73                println!(
 74                    "{:?} (0x{:x}): pc={:?} gas={:?}\nstack:",
 75                    self.opcodes.get(&opcode).unwrap().name,
 76                    opcode,
 77                    self.pc,
 78                    self.gas,
 79                );
 80                self.print_stack();
 81                println!();
 82            }
 83            match opcode & 0xf0 {
 84                0x00 => {
 85                    // arithmetic
 86                    match opcode {
 87                        0x00 => {
 88                            return Vec::new();
 89                        }
 90                        0x01 => self.add(),
 91                        0x02 => self.mul(),
 92                        0x03 => self.sub(),
 93                        0x04 => self.div(),
 94                        0x05 => self.sdiv(),
 95                        0x06 => self.modulus(),
 96                        0x07 => self.smod(),
 97                        0x08 => self.add_mod(),
 98                        0x09 => self.mul_mod(),
 99                        0x0a => self.exp(),
100                        // 0x0b => self.sign_extend(),
101                        _ => panic!("unimplemented {:x}", opcode),
102                    }
103                    self.pc += 1;
104                }
105                0x30 => {
106                    match opcode {
107                        0x35 => {
108                            self.calldata_load(&calldata);
109                        }
110                        _ => panic!("unimplemented {:x}", opcode),
111                    }
112                    self.pc += 1;
113                }
114                0x50 => {
115                    self.pc += 1;
116                    match opcode {
117                        0x51 => self.mload(),
118                        0x52 => self.mstore(),
119                        0x56 => self.jump(),
120                        0x57 => self.jump_i(),
121                        0x5b => self.jump_dest(),
122                        _ => panic!("unimplemented {:x}", opcode),
123                    }
124                }
125                0x60 | 0x70 => {
126                    // push
127                    let n = (opcode - 0x5f) as usize;
128                    self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
129                    self.pc += 1 + n;
130                }
131                0x80 => {
132                    // 0x8x dup
133                    let l = self.stack.len();
134                    if opcode > 0x7f {
135                        self.stack.push(self.stack[l - (opcode - 0x7f) as usize]);
136                    } else {
137                        self.stack.push(self.stack[(0x7f - opcode) as usize]);
138                    }
139                    self.pc += 1;
140                }
141                0x90 => {
142                    // 0x9x swap
143                    let l = self.stack.len();
144                    let pos;
145                    if opcode > 0x8e {
146                        pos = l - (opcode - 0x8e) as usize;
147                    } else {
148                        pos = (0x8e - opcode) as usize;
149                    }
150                    self.stack.swap(pos, l - 1);
151                    self.pc += 1;
152                }
153                0xf0 => {
154                    if opcode == 0xf3 {
155                        let pos_to_return = u256_to_u64(self.pop()) as usize;
156                        let len_to_return = u256_to_u64(self.pop()) as usize;
157                        return self.mem[pos_to_return..pos_to_return + len_to_return].to_vec();
158                    }
159                }
160                _ => {
161                    panic!("unimplemented {:x}", opcode);
162                }
163            }
164            self.gas -= self.opcodes.get(&opcode).unwrap().gas;
165        }
166        Vec::new()
167    }
168}
169
170pub fn u256_to_u64(a: [u8; 32]) -> u64 {
171    let mut b8: [u8; 8] = [0; 8];
172    b8.copy_from_slice(&a[32 - 8..32]);
173    u64::from_be_bytes(b8)
174}
175pub fn str_to_u256(s: &str) -> [u8; 32] {
176    let bi = s.parse::<BigUint>().unwrap().to_bytes_be();
177    let mut r: [u8; 32] = [0; 32];
178    r[32 - bi.len()..].copy_from_slice(&bi[..]);
179    r
180}