evm-rs/src/lib.rs
src/lib.rsRaw
1#![allow(dead_code)]
2
3use num_bigint::BigUint;
4use std::collections::HashMap;
5pub mod opcodes;
6pub mod u256;
7
8#[derive(Default)]
9pub struct Stack {
10 pub pc: usize,
11 pub calldata_i: usize,
12 pub calldata_size: usize,
13 pub stack: Vec<[u8; 32]>,
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: HashMap::new(),
28 mem: Vec::new(),
29 gas: 10000000000,
30 opcodes: HashMap::new(),
31 };
32 s.opcodes = opcodes::new_opcodes();
33 s
34 }
35 pub fn print_stack(&self) {
36 println!("stack ({}):", self.stack.len());
37 for i in (0..self.stack.len()).rev() {
38 // println!("{:x}", &self.stack[i][28..]);
39 println!("{:?}", vec_u8_to_hex(self.stack[i].to_vec()));
40 }
41 }
42 pub fn print_memory(&self) {
43 if self.mem.len() > 0 {
44 println!("memory ({}):", self.mem.len());
45 println!("{:?}", vec_u8_to_hex(self.mem.to_vec()));
46 }
47 }
48 pub fn print_storage(&self) {
49 if self.storage.len() > 0 {
50 println!("storage ({}):", self.storage.len());
51 for (key, value) in self.storage.iter() {
52 println!(
53 "{:?}: {:?}",
54 vec_u8_to_hex(key.to_vec()),
55 vec_u8_to_hex(value.to_vec())
56 );
57 }
58 }
59 }
60 pub fn push(&mut self, b: [u8; 32]) {
61 self.stack.push(b);
62 }
63 // push_arbitrary performs a push, but first converting the arbitrary-length
64 // input into a 32 byte array
65 pub fn push_arbitrary(&mut self, b: &[u8]) {
66 // TODO if b.len()>32 return error
67 let mut d: [u8; 32] = [0; 32];
68 d[32 - b.len()..].copy_from_slice(b);
69 self.stack.push(d);
70 }
71 // put_arbitrary puts in the last element of the stack the value
72 pub fn put_arbitrary(&mut self, b: &[u8]) {
73 // TODO if b.len()>32 return error
74 let mut d: [u8; 32] = [0; 32];
75 d[0..b.len()].copy_from_slice(b); // put without left padding
76 let l = self.stack.len();
77 self.stack[l - 1] = d;
78 }
79 pub fn pop(&mut self) -> [u8; 32] {
80 match self.stack.pop() {
81 Some(x) => x,
82 None => panic!("pop err"),
83 }
84 }
85
86 pub fn execute(&mut self, code: &[u8], calldata: &[u8], debug: bool) -> Vec<u8> {
87 self.pc = 0;
88 self.calldata_i = 0;
89 let l = code.len();
90
91 while self.pc < l {
92 let opcode = code[self.pc];
93 if !self.opcodes.contains_key(&opcode) {
94 panic!("invalid opcode {:x}", opcode);
95 }
96
97 if debug {
98 println!(
99 "{} (0x{:x}): pc={:?} gas={:?}",
100 self.opcodes.get(&opcode).unwrap().name,
101 opcode,
102 self.pc,
103 self.gas,
104 );
105 self.print_stack();
106 self.print_memory();
107 self.print_storage();
108 println!();
109 }
110 match opcode & 0xf0 {
111 0x00 => {
112 // arithmetic
113 match opcode {
114 0x00 => {
115 println!("0x00: STOP");
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 => self.calldata_load(&calldata),
136 0x36 => self.calldata_size(&calldata),
137 0x39 => self.code_copy(&code),
138 _ => panic!("unimplemented {:x}", opcode),
139 }
140 self.pc += 1;
141 }
142 0x50 => {
143 self.pc += 1;
144 match opcode {
145 0x51 => self.mload(),
146 0x52 => self.mstore(),
147 0x55 => self.sstore(),
148 0x56 => self.jump(),
149 0x57 => self.jump_i(),
150 0x5b => self.jump_dest(),
151 _ => panic!("unimplemented {:x}", opcode),
152 }
153 }
154 0x60 | 0x70 => {
155 // push
156 let n = (opcode - 0x5f) as usize;
157 self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
158 self.pc += 1 + n;
159 }
160 0x80 => {
161 // 0x8x dup
162 let l = self.stack.len();
163 if opcode > 0x7f {
164 self.stack.push(self.stack[l - (opcode - 0x7f) as usize]);
165 } else {
166 self.stack.push(self.stack[(0x7f - opcode) as usize]);
167 }
168 self.pc += 1;
169 }
170 0x90 => {
171 // 0x9x swap
172 let l = self.stack.len();
173 let pos;
174 if opcode > 0x8e {
175 pos = l - (opcode - 0x8e) as usize;
176 } else {
177 pos = (0x8e - opcode) as usize;
178 }
179 self.stack.swap(pos, l - 1);
180 self.pc += 1;
181 }
182 0xf0 => {
183 if opcode == 0xf3 {
184 let pos_to_return = u256::u256_to_u64(self.pop()) as usize;
185 let len_to_return = u256::u256_to_u64(self.pop()) as usize;
186 return self.mem[pos_to_return..pos_to_return + len_to_return].to_vec();
187 }
188 }
189 _ => {
190 return panic!("unimplemented {:x}", opcode);
191 }
192 }
193 self.gas -= self.opcodes.get(&opcode).unwrap().gas;
194 }
195 Vec::new()
196 }
197}
198pub fn vec_u8_to_hex(bytes: Vec<u8>) -> String {
199 let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
200 strs.join("")
201}