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;
  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 print_stack(&self) {
 60        for i in (0..self.stack.len()).rev() {
 61            println!("{:x?}", &self.stack[i][28..]);
 62        }
 63    }
 64    fn push(&mut self, b: [u8; 32]) {
 65        self.stack.push(b);
 66    }
 67    // push_arbitrary performs a push, but first converting the arbitrary-length input into a 32
 68    // byte array
 69    fn push_arbitrary(&mut self, b: &[u8]) {
 70        // TODO if b.len()>32 return error
 71        let mut d: [u8; 32] = [0; 32];
 72        d[32 - b.len()..].copy_from_slice(&b[..]);
 73        self.stack.push(d);
 74    }
 75    // put_arbitrary puts in the last element of the stack the value
 76    fn put_arbitrary(&mut self, b: &[u8]) {
 77        // TODO if b.len()>32 return error
 78        let mut d: [u8; 32] = [0; 32];
 79        d[32 - b.len()..].copy_from_slice(&b[..]);
 80        let l = self.stack.len();
 81        self.stack[l - 1] = d;
 82    }
 83    fn pop(&mut self) -> [u8; 32] {
 84        match self.stack.pop() {
 85            Some(x) => return x,
 86            None => panic!("err"),
 87        }
 88    }
 89    fn execute(&mut self, code: &[u8], calldata: &[u8], debug: bool) -> Vec<u8> {
 90        self.pc = 0;
 91        self.calldata_i = 0;
 92        let l = code.len();
 93
 94        while self.pc < l {
 95            let opcode = code[self.pc];
 96            if !self.opcodes.contains_key(&opcode) {
 97                panic!("invalid opcode {:x}", opcode);
 98            }
 99
100            if debug {
101                println!(
102                    "{:?} (0x{:x}): pc={:?} gas={:?}\nstack:",
103                    self.opcodes.get(&opcode).unwrap().name,
104                    opcode,
105                    self.pc,
106                    self.gas,
107                );
108                self.print_stack();
109                println!("");
110            }
111            match opcode & 0xf0 {
112                0x00 => {
113                    // arithmetic
114                    match opcode {
115                        0x00 => {
116                            return Vec::new();
117                        }
118                        0x01 => self.add(),
119                        0x02 => self.mul(),
120                        0x03 => self.sub(),
121                        0x04 => self.div(),
122                        0x05 => self.sdiv(),
123                        0x06 => self.modulus(),
124                        0x07 => self.smod(),
125                        0x08 => self.add_mod(),
126                        0x09 => self.mul_mod(),
127                        0x0a => self.exp(),
128                        // 0x0b => self.sign_extend(),
129                        _ => panic!("unimplemented {:x}", opcode),
130                    }
131                    self.pc += 1;
132                }
133                0x30 => {
134                    match opcode {
135                        0x35 => {
136                            self.calldata_load(&calldata);
137                        }
138                        _ => panic!("unimplemented {:x}", opcode),
139                    }
140                    self.pc += 1;
141                }
142                0x50 => {
143                    self.pc += 1;
144                    match opcode {
145                        0x52 => self.mstore(),
146                        _ => panic!("unimplemented {:x}", opcode),
147                    }
148                }
149                0x60 | 0x70 => {
150                    // push
151                    let n = (opcode - 0x5f) as usize;
152                    self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
153                    self.pc += 1 + n;
154                }
155                0xf0 => {
156                    if opcode == 0xf3 {
157                        let pos_to_return = u256_to_u64(self.pop()) as usize;
158                        let len_to_return = u256_to_u64(self.pop()) as usize;
159                        return self.mem[pos_to_return..pos_to_return + len_to_return].to_vec();
160                    }
161                }
162                _ => {
163                    panic!("unimplemented {:x}", opcode);
164                }
165            }
166            self.gas -= self.opcodes.get(&opcode).unwrap().gas;
167        }
168        return Vec::new();
169    }
170
171    // arithmetic
172    // TODO instead of [u8;32] converted to BigUint, use custom type uint256 that implements all
173    // the arithmetic
174    fn add(&mut self) {
175        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
176        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
177        self.push_arbitrary(&(b0 + b1).to_bytes_be());
178    }
179    fn mul(&mut self) {
180        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
181        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
182        self.push_arbitrary(&(b0 * b1).to_bytes_be());
183    }
184    fn sub(&mut self) {
185        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
186        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
187        if b0 >= b1 {
188            self.push_arbitrary(&(b0 - b1).to_bytes_be());
189        } else {
190            // 2**256
191            let max =
192                "115792089237316195423570985008687907853269984665640564039457584007913129639936"
193                    .parse::<BigUint>()
194                    .unwrap();
195            self.push_arbitrary(&(max + b0 - b1).to_bytes_be());
196        }
197    }
198    fn div(&mut self) {
199        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
200        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
201        self.push_arbitrary(&(b0 / b1).to_bytes_be());
202    }
203    fn sdiv(&mut self) {
204        panic!("unimplemented");
205    }
206    fn modulus(&mut self) {
207        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
208        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
209        self.push_arbitrary(&(b0 % b1).to_bytes_be());
210    }
211    fn smod(&mut self) {
212        panic!("unimplemented");
213    }
214    fn add_mod(&mut self) {
215        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
216        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
217        let b2 = BigUint::from_bytes_be(&self.pop()[..]);
218        self.push_arbitrary(&(b0 + b1 % b2).to_bytes_be());
219    }
220    fn mul_mod(&mut self) {
221        let b0 = BigUint::from_bytes_be(&self.pop()[..]);
222        let b1 = BigUint::from_bytes_be(&self.pop()[..]);
223        let b2 = BigUint::from_bytes_be(&self.pop()[..]);
224        self.push_arbitrary(&(b0 * b1 % b2).to_bytes_be());
225    }
226    fn exp(&mut self) {
227        panic!("unimplemented");
228        // let b0 = BigUint::from_bytes_be(&self.pop()[..]);
229        // let b1 = BigUint::from_bytes_be(&self.pop()[..]);
230        // self.push_arbitrary(&(pow(b0, b1)).to_bytes_be());
231    }
232
233    // boolean
234    // crypto
235
236    // contract context
237    fn calldata_load(&mut self, calldata: &[u8]) {
238        self.put_arbitrary(&calldata[self.calldata_i..self.calldata_i + 32]);
239        self.calldata_i += 32;
240    }
241
242    // blockchain context
243
244    // storage and execution
245    fn extend_mem(&mut self, start: usize, size: usize) {
246        if size <= self.mem.len() || start + size <= self.mem.len() {
247            return;
248        }
249        let old_size = self.mem.len() / 32;
250        let new_size = (start + size) / 32;
251        let old_total_fee = old_size * GMEMORY + old_size.pow(2) / GQUADRATICMEMDENOM;
252        let new_total_fee = new_size * GMEMORY + new_size.pow(2) / GQUADRATICMEMDENOM;
253        let mem_fee = new_total_fee - old_total_fee;
254        self.gas -= mem_fee as u64;
255        let mut new_bytes: Vec<u8> = vec![0; size];
256        self.mem.append(&mut new_bytes);
257    }
258    fn mstore(&mut self) {
259        let pos = u256_to_u64(self.pop());
260        let val = self.pop();
261        self.extend_mem(pos as usize, 32);
262
263        self.mem[pos as usize..].copy_from_slice(&val);
264    }
265}
266
267fn u256_to_u64(a: [u8; 32]) -> u64 {
268    let mut b8: [u8; 8] = [0; 8];
269    b8.copy_from_slice(&a[32 - 8..32]);
270    let pos = u64::from_be_bytes(b8);
271    pos
272}
273fn str_to_u256(s: &str) -> [u8; 32] {
274    let bi = s.parse::<BigUint>().unwrap().to_bytes_be();
275    let mut r: [u8; 32] = [0; 32];
276    r[32 - bi.len()..].copy_from_slice(&bi[..]);
277    r
278}
279
280struct Opcode {
281    name: String,
282    ins: u32,
283    outs: u32,
284    gas: u64,
285}
286
287fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
288    Opcode {
289        name: name.to_string(),
290        ins,
291        outs,
292        gas,
293    }
294}
295
296fn new_opcodes() -> HashMap<u8, Opcode> {
297    let mut opcodes: HashMap<u8, Opcode> = HashMap::new();
298
299    // arithmetic
300    opcodes.insert(0x00, new_opcode("STOP", 0, 0, 0));
301    opcodes.insert(0x01, new_opcode("ADD", 2, 1, 3));
302    opcodes.insert(0x02, new_opcode("MUL", 2, 1, 5));
303    opcodes.insert(0x03, new_opcode("SUB", 2, 1, 3));
304    opcodes.insert(0x04, new_opcode("DIV", 2, 1, 5));
305    opcodes.insert(0x05, new_opcode("SDIV", 2, 1, 5));
306    opcodes.insert(0x06, new_opcode("MOD", 2, 1, 5));
307    opcodes.insert(0x07, new_opcode("SMOD", 2, 1, 5));
308    opcodes.insert(0x08, new_opcode("ADDMOD", 3, 1, 8));
309    opcodes.insert(0x09, new_opcode("MULMOD", 3, 1, 8));
310    opcodes.insert(0x0a, new_opcode("EXP", 2, 1, 10));
311    opcodes.insert(0x0b, new_opcode("SIGNEXTEND", 2, 1, 5));
312
313    // boolean
314    opcodes.insert(0x10, new_opcode("LT", 2, 1, 3));
315    opcodes.insert(0x11, new_opcode("GT", 2, 1, 3));
316    opcodes.insert(0x12, new_opcode("SLT", 2, 1, 3));
317    opcodes.insert(0x13, new_opcode("SGT", 2, 1, 3));
318    opcodes.insert(0x14, new_opcode("EQ", 2, 1, 3));
319    opcodes.insert(0x15, new_opcode("ISZERO", 1, 1, 3));
320    opcodes.insert(0x16, new_opcode("AND", 2, 1, 3));
321    opcodes.insert(0x17, new_opcode("OR", 2, 1, 3));
322    opcodes.insert(0x18, new_opcode("XOR", 2, 1, 3));
323    opcodes.insert(0x19, new_opcode("NOT", 1, 1, 3));
324    opcodes.insert(0x1a, new_opcode("BYTE", 2, 1, 3));
325
326    // crypto
327    opcodes.insert(0x20, new_opcode("SHA3", 2, 1, 30));
328
329    // contract context
330    opcodes.insert(0x30, new_opcode("ADDRESS", 0, 1, 2));
331    opcodes.insert(0x31, new_opcode("BALANCE", 1, 1, 20));
332    opcodes.insert(0x32, new_opcode("ORIGIN", 0, 1, 2));
333    opcodes.insert(0x33, new_opcode("CALLER", 0, 1, 2));
334    opcodes.insert(0x34, new_opcode("CALLVALUE", 0, 1, 2));
335    opcodes.insert(0x35, new_opcode("CALLDATALOAD", 1, 1, 3));
336    opcodes.insert(0x36, new_opcode("CALLDATASIZE", 0, 1, 2));
337    opcodes.insert(0x37, new_opcode("CALLDATACOPY", 3, 0, 3));
338    opcodes.insert(0x38, new_opcode("CODESIZE", 0, 1, 2));
339    opcodes.insert(0x39, new_opcode("CODECOPY", 3, 0, 3));
340    opcodes.insert(0x3a, new_opcode("GASPRICE", 0, 1, 2));
341    opcodes.insert(0x3b, new_opcode("EXTCODESIZE", 1, 1, 20));
342    opcodes.insert(0x3c, new_opcode("EXTCODECOPY", 4, 0, 20));
343
344    // blockchain context
345    opcodes.insert(0x40, new_opcode("BLOCKHASH", 1, 1, 20));
346    opcodes.insert(0x41, new_opcode("COINBASE", 0, 1, 2));
347    opcodes.insert(0x42, new_opcode("TIMESTAMP", 0, 1, 2));
348    opcodes.insert(0x43, new_opcode("NUMBER", 0, 1, 2));
349    opcodes.insert(0x44, new_opcode("DIFFICULTY", 0, 1, 2));
350    opcodes.insert(0x45, new_opcode("GASLIMIT", 0, 1, 2));
351
352    // storage and execution
353    opcodes.insert(0x50, new_opcode("POP", 1, 0, 2));
354    opcodes.insert(0x51, new_opcode("MLOAD", 1, 1, 3));
355    opcodes.insert(0x52, new_opcode("MSTORE", 2, 0, 3));
356    opcodes.insert(0x53, new_opcode("MSTORE8", 2, 0, 3));
357    opcodes.insert(0x54, new_opcode("SLOAD", 1, 1, 50));
358    opcodes.insert(0x55, new_opcode("SSTORE", 2, 0, 0));
359    opcodes.insert(0x56, new_opcode("JUMP", 1, 0, 8));
360    opcodes.insert(0x57, new_opcode("JUMPI", 2, 0, 10));
361    opcodes.insert(0x58, new_opcode("PC", 0, 1, 2));
362    opcodes.insert(0x59, new_opcode("MSIZE", 0, 1, 2));
363    opcodes.insert(0x5a, new_opcode("GAS", 0, 1, 2));
364    opcodes.insert(0x5b, new_opcode("JUMPDEST", 0, 0, 1));
365
366    // logging
367    opcodes.insert(0xa0, new_opcode("LOG0", 2, 0, 375));
368    opcodes.insert(0xa1, new_opcode("LOG1", 3, 0, 750));
369    opcodes.insert(0xa2, new_opcode("LOG2", 4, 0, 1125));
370    opcodes.insert(0xa3, new_opcode("LOG3", 5, 0, 1500));
371    opcodes.insert(0xa4, new_opcode("LOG4", 6, 0, 1875));
372
373    // closures
374    opcodes.insert(0xf0, new_opcode("CREATE", 3, 1, 32000));
375    opcodes.insert(0xf1, new_opcode("CALL", 7, 1, 40));
376    opcodes.insert(0xf2, new_opcode("CALLCODE", 7, 1, 40));
377    opcodes.insert(0xf3, new_opcode("RETURN", 2, 0, 0));
378    opcodes.insert(0xf4, new_opcode("DELEGATECALL", 6, 0, 40));
379    opcodes.insert(0xff, new_opcode("SUICIDE", 1, 0, 0));
380
381    for i in 1..33 {
382        let name = format!("PUSH{}", i);
383        opcodes.insert(0x5f + i, new_opcode(&name, 0, 1, 3));
384    }
385
386    for i in 1..17 {
387        let name = format!("DUP{}", i);
388        opcodes.insert(0x7f + i, new_opcode(&name, i as u32, i as u32 + 1, 3));
389
390        let name = format!("SWAP{}", i);
391        opcodes.insert(0x8f + i, new_opcode(&name, i as u32 + 1, i as u32 + 1, 3));
392    }
393
394    opcodes
395}
396
397#[cfg(test)]
398mod tests {
399    use super::*;
400
401    #[test]
402    fn stack_simple_push_pop() {
403        let mut s = Stack::new();
404        s.push(str_to_u256("1"));
405        s.push(str_to_u256("2"));
406        s.push(str_to_u256("3"));
407        assert_eq!(s.pop(), str_to_u256("3"));
408        assert_eq!(s.pop(), str_to_u256("2"));
409        assert_eq!(s.pop(), str_to_u256("1"));
410        // assert_eq!(s.pop(), str_to_u256("1"));
411        // assert_eq!(s.pop(), error); // TODO expect error as stack is empty
412    }
413
414    // arithmetic
415    #[test]
416    fn execute_opcodes_0() {
417        let code = hex::decode("6005600c01").unwrap(); // 5+12
418        let calldata = vec![];
419
420        let mut s = Stack::new();
421        s.execute(&code, &calldata, false);
422        assert_eq!(s.pop(), str_to_u256("17"));
423        assert_eq!(s.gas, 9999999991);
424        assert_eq!(s.pc, 5);
425    }
426
427    #[test]
428    fn execute_opcodes_1() {
429        let code = hex::decode("60056004016000526001601ff3").unwrap();
430        let calldata = vec![];
431
432        let mut s = Stack::new();
433        let out = s.execute(&code, &calldata, false);
434
435        assert_eq!(out[0], 0x09);
436        assert_eq!(s.gas, 9999999976);
437        assert_eq!(s.pc, 12);
438        // assert_eq!(s.pop(), err); // TODO expect error as stack is empty
439    }
440
441    #[test]
442    fn execute_opcodes_2() {
443        let code = hex::decode("61010161010201").unwrap();
444        let calldata = vec![];
445
446        let mut s = Stack::new();
447        s.execute(&code, &calldata, false);
448
449        // assert_eq!(out[0], 0x09);
450        assert_eq!(s.gas, 9999999991);
451        assert_eq!(s.pc, 7);
452        assert_eq!(s.pop(), str_to_u256("515"));
453    }
454
455    #[test]
456    fn execute_opcodes_3() {
457        // contains calldata
458        let code = hex::decode("60003560203501").unwrap();
459        let calldata = hex::decode("00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004").unwrap();
460
461        let mut s = Stack::new();
462        s.execute(&code, &calldata, false);
463
464        assert_eq!(s.gas, 9999999985);
465        assert_eq!(s.pc, 7);
466        assert_eq!(s.pop(), str_to_u256("9"));
467    }
468}