evm-rs/src/lib.rs
src/lib.rsRaw
1#![allow(dead_code)]
2
3use num_bigint::BigUint;
4use std::collections::HashMap;
5
6// Non-opcode gas prices
7const GDEFAULT: usize = 1;
8const GMEMORY: usize = 3;
9const GQUADRATICMEMDENOM: usize = 512; // 1 gas per 512 quadwords
10const GSTORAGEREFUND: usize = 15000;
11const GSTORAGEKILL: usize = 5000;
12const GSTORAGEMOD: usize = 5000;
13const GSTORAGEADD: usize = 20000;
14const GEXPONENTBYTE: usize = 10; // cost of EXP exponent per byte
15const GCOPY: usize = 3; // cost to copy one 32 byte word
16const GCONTRACTBYTE: usize = 200; // one byte of code in contract creation
17const GCALLVALUETRANSFER: usize = 9000; // non-zero-valued call
18const GLOGBYTE: usize = 8; // cost of a byte of logdata
19
20const GTXCOST: usize = 21000; // TX BASE GAS COST
21const GTXDATAZERO: usize = 4; // TX DATA ZERO BYTE GAS COST
22const GTXDATANONZERO: usize = 68; // TX DATA NON ZERO BYTE GAS COST
23const GSHA3WORD: usize = 6; // Cost of SHA3 per word
24const GSHA256BASE: usize = 60; // Base c of SHA256
25const GSHA256WORD: usize = 12; // Cost of SHA256 per word
26const GRIPEMD160BASE: usize = 600; // Base cost of RIPEMD160
27const GRIPEMD160WORD: usize = 120; // Cost of RIPEMD160 per word
28const GIDENTITYBASE: usize = 15; // Base cost of indentity
29const GIDENTITYWORD: usize = 3; // Cost of identity per word
30const GECRECOVER: usize = 3000; // Cost of ecrecover op
31
32const GSTIPEND: usize = 2300;
33
34const GCALLNEWACCOUNT: usize = 25000;
35const GSUICIDEREFUND: usize = 24000;
36
37pub struct Stack {
38 pc: usize,
39 calldata_i: usize,
40 stack: Vec<[u8; 32]>,
41 mem: Vec<u8>,
42 gas: u64,
43 opcodes: HashMap<u8, Opcode>,
44}
45
46impl Stack {
47 pub fn new() -> Stack {
48 let mut s = Stack {
49 pc: 0,
50 calldata_i: 0,
51 stack: Vec::new(),
52 mem: Vec::new(),
53 gas: 10000000000,
54 opcodes: HashMap::new(),
55 };
56 s.opcodes = new_opcodes();
57 s
58 }
59 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 input into a 32
63 // byte array
64 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 fn pop(&mut self) -> [u8; 32] {
71 match self.stack.pop() {
72 Some(x) => return x,
73 None => panic!("err"),
74 }
75 }
76 fn execute(&mut self, code: &[u8], calldata: &[u8], debug: bool) -> Vec<u8> {
77 self.pc = 0;
78 self.calldata_i = 0;
79 let l = code.len();
80
81 while self.pc < l {
82 let opcode = code[self.pc];
83 if !self.opcodes.contains_key(&opcode) {
84 panic!("invalid opcode {:x}", opcode);
85 }
86
87 match opcode & 0xf0 {
88 0x00 => {
89 // arithmetic
90 match opcode {
91 0x00 => {
92 return Vec::new();
93 }
94 0x01 => self.add(),
95 0x02 => self.mul(),
96 0x03 => self.sub(),
97 0x04 => self.div(),
98 0x05 => self.sdiv(),
99 0x06 => self.modulus(),
100 0x07 => self.smod(),
101 0x08 => self.add_mod(),
102 0x09 => self.mul_mod(),
103 0x0a => self.exp(),
104 // 0x0b => self.sign_extend(),
105 _ => panic!("unimplemented {:x}", opcode),
106 }
107 self.pc += 1;
108 }
109 0x50 => {
110 self.pc += 1;
111 match opcode {
112 0x52 => self.mstore(),
113 _ => panic!("unimplemented {:x}", opcode),
114 }
115 }
116 0x60 | 0x70 => {
117 // push
118 let n = (opcode - 0x5f) as usize;
119 self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
120 self.pc += 1 + n;
121 }
122 0xf0 => {
123 if opcode == 0xf3 {
124 let pos_to_return = u256_to_u64(self.pop()) as usize;
125 let len_to_return = u256_to_u64(self.pop()) as usize;
126 return self.mem[pos_to_return..pos_to_return + len_to_return].to_vec();
127 }
128 }
129 _ => {
130 panic!("unimplemented {:x}", opcode);
131 }
132 }
133 self.gas -= self.opcodes.get(&opcode).unwrap().gas;
134 }
135 return Vec::new();
136 }
137
138 // arithmetic
139 // TODO instead of [u8;32] converted to BigUint, use custom type uint256 that implements all
140 // the arithmetic
141 fn add(&mut self) {
142 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
143 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
144 self.push_arbitrary(&(b0 + b1).to_bytes_be());
145 }
146 fn mul(&mut self) {
147 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
148 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
149 self.push_arbitrary(&(b0 * b1).to_bytes_be());
150 }
151 fn sub(&mut self) {
152 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
153 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
154 if b0 >= b1 {
155 self.push_arbitrary(&(b0 - b1).to_bytes_be());
156 } else {
157 // 2**256
158 let max =
159 "115792089237316195423570985008687907853269984665640564039457584007913129639936"
160 .parse::<BigUint>()
161 .unwrap();
162 self.push_arbitrary(&(max + b0 - b1).to_bytes_be());
163 }
164 }
165 fn div(&mut self) {
166 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
167 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
168 self.push_arbitrary(&(b0 / b1).to_bytes_be());
169 }
170 fn sdiv(&mut self) {
171 panic!("unimplemented");
172 }
173 fn modulus(&mut self) {
174 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
175 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
176 self.push_arbitrary(&(b0 % b1).to_bytes_be());
177 }
178 fn smod(&mut self) {
179 panic!("unimplemented");
180 }
181 fn add_mod(&mut self) {
182 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
183 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
184 let b2 = BigUint::from_bytes_be(&self.pop()[..]);
185 self.push_arbitrary(&(b0 + b1 % b2).to_bytes_be());
186 }
187 fn mul_mod(&mut self) {
188 let b0 = BigUint::from_bytes_be(&self.pop()[..]);
189 let b1 = BigUint::from_bytes_be(&self.pop()[..]);
190 let b2 = BigUint::from_bytes_be(&self.pop()[..]);
191 self.push_arbitrary(&(b0 * b1 % b2).to_bytes_be());
192 }
193 fn exp(&mut self) {
194 panic!("unimplemented");
195 // let b0 = BigUint::from_bytes_be(&self.pop()[..]);
196 // let b1 = BigUint::from_bytes_be(&self.pop()[..]);
197 // self.push_arbitrary(&(pow(b0, b1)).to_bytes_be());
198 }
199
200 // boolean
201 // crypto
202
203 // contract context
204 fn calldata_load(&mut self, calldata: &[u8]) {}
205
206 // blockchain context
207
208 // storage and execution
209 fn extend_mem(&mut self, start: usize, size: usize) {
210 if size <= self.mem.len() || start + size <= self.mem.len() {
211 return;
212 }
213 let old_size = self.mem.len() / 32;
214 let new_size = (start + size) / 32;
215 let old_total_fee = old_size * GMEMORY + old_size.pow(2) / GQUADRATICMEMDENOM;
216 let new_total_fee = new_size * GMEMORY + new_size.pow(2) / GQUADRATICMEMDENOM;
217 let mem_fee = new_total_fee - old_total_fee;
218 self.gas -= mem_fee as u64;
219 let mut new_bytes: Vec<u8> = vec![0; size];
220 self.mem.append(&mut new_bytes);
221 }
222 fn mstore(&mut self) {
223 let pos = u256_to_u64(self.pop());
224 let val = self.pop();
225 self.extend_mem(pos as usize, 32);
226
227 self.mem[pos as usize..].copy_from_slice(&val);
228 }
229}
230
231fn u256_to_u64(a: [u8; 32]) -> u64 {
232 let mut b8: [u8; 8] = [0; 8];
233 b8.copy_from_slice(&a[32 - 8..32]);
234 let pos = u64::from_be_bytes(b8);
235 pos
236}
237fn str_to_u256(s: &str) -> [u8; 32] {
238 let bi = s.parse::<BigUint>().unwrap().to_bytes_be();
239 let mut r: [u8; 32] = [0; 32];
240 r[32 - bi.len()..].copy_from_slice(&bi[..]);
241 r
242}
243
244struct Opcode {
245 name: String,
246 ins: u32,
247 outs: u32,
248 gas: u64,
249}
250
251fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
252 Opcode {
253 name: name.to_string(),
254 ins,
255 outs,
256 gas,
257 }
258}
259
260fn new_opcodes() -> HashMap<u8, Opcode> {
261 let mut opcodes: HashMap<u8, Opcode> = HashMap::new();
262
263 // arithmetic
264 opcodes.insert(0x00, new_opcode("STOP", 0, 0, 0));
265 opcodes.insert(0x01, new_opcode("ADD", 2, 1, 3));
266 opcodes.insert(0x02, new_opcode("MUL", 2, 1, 5));
267 opcodes.insert(0x03, new_opcode("SUB", 2, 1, 3));
268 opcodes.insert(0x04, new_opcode("DIV", 2, 1, 5));
269 opcodes.insert(0x05, new_opcode("SDIV", 2, 1, 5));
270 opcodes.insert(0x06, new_opcode("MOD", 2, 1, 5));
271 opcodes.insert(0x07, new_opcode("SMOD", 2, 1, 5));
272 opcodes.insert(0x08, new_opcode("ADDMOD", 3, 1, 8));
273 opcodes.insert(0x09, new_opcode("MULMOD", 3, 1, 8));
274 opcodes.insert(0x0a, new_opcode("EXP", 2, 1, 10));
275 opcodes.insert(0x0b, new_opcode("SIGNEXTEND", 2, 1, 5));
276
277 // boolean
278 opcodes.insert(0x10, new_opcode("LT", 2, 1, 3));
279 opcodes.insert(0x11, new_opcode("GT", 2, 1, 3));
280 opcodes.insert(0x12, new_opcode("SLT", 2, 1, 3));
281 opcodes.insert(0x13, new_opcode("SGT", 2, 1, 3));
282 opcodes.insert(0x14, new_opcode("EQ", 2, 1, 3));
283 opcodes.insert(0x15, new_opcode("ISZERO", 1, 1, 3));
284 opcodes.insert(0x16, new_opcode("AND", 2, 1, 3));
285 opcodes.insert(0x17, new_opcode("OR", 2, 1, 3));
286 opcodes.insert(0x18, new_opcode("XOR", 2, 1, 3));
287 opcodes.insert(0x19, new_opcode("NOT", 1, 1, 3));
288 opcodes.insert(0x1a, new_opcode("BYTE", 2, 1, 3));
289
290 // crypto
291 opcodes.insert(0x20, new_opcode("SHA3", 2, 1, 30));
292
293 // contract context
294 opcodes.insert(0x30, new_opcode("ADDRESS", 0, 1, 2));
295 opcodes.insert(0x31, new_opcode("BALANCE", 1, 1, 20));
296 opcodes.insert(0x32, new_opcode("ORIGIN", 0, 1, 2));
297 opcodes.insert(0x33, new_opcode("CALLER", 0, 1, 2));
298 opcodes.insert(0x34, new_opcode("CALLVALUE", 0, 1, 2));
299 opcodes.insert(0x35, new_opcode("CALLDATALOAD", 1, 1, 3));
300 opcodes.insert(0x36, new_opcode("CALLDATASIZE", 0, 1, 2));
301 opcodes.insert(0x37, new_opcode("CALLDATACOPY", 3, 0, 3));
302 opcodes.insert(0x38, new_opcode("CODESIZE", 0, 1, 2));
303 opcodes.insert(0x39, new_opcode("CODECOPY", 3, 0, 3));
304 opcodes.insert(0x3a, new_opcode("GASPRICE", 0, 1, 2));
305 opcodes.insert(0x3b, new_opcode("EXTCODESIZE", 1, 1, 20));
306 opcodes.insert(0x3c, new_opcode("EXTCODECOPY", 4, 0, 20));
307
308 // blockchain context
309 opcodes.insert(0x40, new_opcode("BLOCKHASH", 1, 1, 20));
310 opcodes.insert(0x41, new_opcode("COINBASE", 0, 1, 2));
311 opcodes.insert(0x42, new_opcode("TIMESTAMP", 0, 1, 2));
312 opcodes.insert(0x43, new_opcode("NUMBER", 0, 1, 2));
313 opcodes.insert(0x44, new_opcode("DIFFICULTY", 0, 1, 2));
314 opcodes.insert(0x45, new_opcode("GASLIMIT", 0, 1, 2));
315
316 // storage and execution
317 opcodes.insert(0x50, new_opcode("POP", 1, 0, 2));
318 opcodes.insert(0x51, new_opcode("MLOAD", 1, 1, 3));
319 opcodes.insert(0x52, new_opcode("MSTORE", 2, 0, 3));
320 opcodes.insert(0x53, new_opcode("MSTORE8", 2, 0, 3));
321 opcodes.insert(0x54, new_opcode("SLOAD", 1, 1, 50));
322 opcodes.insert(0x55, new_opcode("SSTORE", 2, 0, 0));
323 opcodes.insert(0x56, new_opcode("JUMP", 1, 0, 8));
324 opcodes.insert(0x57, new_opcode("JUMPI", 2, 0, 10));
325 opcodes.insert(0x58, new_opcode("PC", 0, 1, 2));
326 opcodes.insert(0x59, new_opcode("MSIZE", 0, 1, 2));
327 opcodes.insert(0x5a, new_opcode("GAS", 0, 1, 2));
328 opcodes.insert(0x5b, new_opcode("JUMPDEST", 0, 0, 1));
329
330 // logging
331 opcodes.insert(0xa0, new_opcode("LOG0", 2, 0, 375));
332 opcodes.insert(0xa1, new_opcode("LOG1", 3, 0, 750));
333 opcodes.insert(0xa2, new_opcode("LOG2", 4, 0, 1125));
334 opcodes.insert(0xa3, new_opcode("LOG3", 5, 0, 1500));
335 opcodes.insert(0xa4, new_opcode("LOG4", 6, 0, 1875));
336
337 // closures
338 opcodes.insert(0xf0, new_opcode("CREATE", 3, 1, 32000));
339 opcodes.insert(0xf1, new_opcode("CALL", 7, 1, 40));
340 opcodes.insert(0xf2, new_opcode("CALLCODE", 7, 1, 40));
341 opcodes.insert(0xf3, new_opcode("RETURN", 2, 0, 0));
342 opcodes.insert(0xf4, new_opcode("DELEGATECALL", 6, 0, 40));
343 opcodes.insert(0xff, new_opcode("SUICIDE", 1, 0, 0));
344
345 for i in 1..33 {
346 let name = format!("PUSH{}", i);
347 opcodes.insert(0x5f + i, new_opcode(&name, 0, 1, 3));
348 }
349
350 for i in 1..17 {
351 let name = format!("DUP{}", i);
352 opcodes.insert(0x7f + i, new_opcode(&name, i as u32, i as u32 + 1, 3));
353
354 let name = format!("SWAP{}", i);
355 opcodes.insert(0x8f + i, new_opcode(&name, i as u32 + 1, i as u32 + 1, 3));
356 }
357
358 opcodes
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364
365 #[test]
366 fn stack_simple_push_pop() {
367 let mut s = Stack::new();
368 s.push(str_to_u256("1"));
369 s.push(str_to_u256("2"));
370 s.push(str_to_u256("3"));
371 assert_eq!(s.pop(), str_to_u256("3"));
372 assert_eq!(s.pop(), str_to_u256("2"));
373 assert_eq!(s.pop(), str_to_u256("1"));
374 // assert_eq!(s.pop(), str_to_u256("1"));
375 // assert_eq!(s.pop(), error); // TODO expect error as stack is empty
376 }
377
378 // arithmetic
379 #[test]
380 fn execute_opcodes_0() {
381 let code = hex::decode("6005600c01").unwrap(); // 5+12
382 let calldata = vec![];
383
384 let mut s = Stack::new();
385 s.execute(&code, &calldata, false);
386 assert_eq!(s.pop(), str_to_u256("17"));
387 assert_eq!(s.gas, 9999999991);
388 assert_eq!(s.pc, 5);
389 }
390
391 #[test]
392 fn execute_opcodes_1() {
393 let code = hex::decode("60056004016000526001601ff3").unwrap();
394 let calldata = vec![];
395
396 let mut s = Stack::new();
397 let out = s.execute(&code, &calldata, false);
398
399 assert_eq!(out[0], 0x09);
400 assert_eq!(s.gas, 9999999976);
401 assert_eq!(s.pc, 12);
402 // assert_eq!(s.pop(), err); // TODO expect error as stack is empty
403 }
404
405 #[test]
406 fn execute_opcodes_2() {
407 let code = hex::decode("61010161010201").unwrap();
408 let calldata = vec![];
409
410 let mut s = Stack::new();
411 s.execute(&code, &calldata, false);
412
413 // assert_eq!(out[0], 0x09);
414 assert_eq!(s.gas, 9999999991);
415 assert_eq!(s.pc, 7);
416 assert_eq!(s.pop(), str_to_u256("515"));
417 }
418}