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