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) -> Result<[u8; 32], String> {
80 match self.stack.pop() {
81 Some(x) => Ok(x),
82 None => Err(format!("pop err")), // WIP
83 }
84 }
85
86 pub fn execute(
87 &mut self,
88 code: &[u8],
89 calldata: &[u8],
90 debug: bool,
91 ) -> Result<Vec<u8>, String> {
92 self.pc = 0;
93 self.calldata_i = 0;
94 let l = code.len();
95
96 while self.pc < l {
97 let opcode = code[self.pc];
98 if !self.opcodes.contains_key(&opcode) {
99 return Err(format!("invalid opcode {:x}", opcode));
100 }
101
102 if debug {
103 println!(
104 "{} (0x{:x}): pc={:?} gas={:?}",
105 self.opcodes.get(&opcode).unwrap().name,
106 opcode,
107 self.pc,
108 self.gas,
109 );
110 self.print_stack();
111 self.print_memory();
112 self.print_storage();
113 println!();
114 }
115 match opcode & 0xf0 {
116 0x00 => {
117 // arithmetic
118 match opcode {
119 0x00 => {
120 println!("0x00: STOP");
121 return Ok(Vec::new());
122 }
123 0x01 => self.add()?,
124 0x02 => self.mul()?,
125 0x03 => self.sub()?,
126 0x04 => self.div()?,
127 0x05 => self.sdiv()?,
128 0x06 => self.modulus()?,
129 0x07 => self.smod()?,
130 0x08 => self.add_mod()?,
131 0x09 => self.mul_mod()?,
132 0x0a => self.exp()?,
133 // 0x0b => self.sign_extend(),
134 _ => return Err(format!("unimplemented {:x}", opcode)),
135 }
136 self.pc += 1;
137 }
138 0x30 => {
139 match opcode {
140 0x35 => self.calldata_load(&calldata),
141 0x36 => self.calldata_size(&calldata),
142 0x39 => self.code_copy(&code)?,
143 _ => return Err(format!("unimplemented {:x}", opcode)),
144 }
145 self.pc += 1;
146 }
147 0x50 => {
148 self.pc += 1;
149 match opcode {
150 0x51 => self.mload()?,
151 0x52 => self.mstore()?,
152 0x55 => self.sstore()?,
153 0x56 => self.jump()?,
154 0x57 => self.jump_i()?,
155 0x5b => self.jump_dest()?,
156 _ => return Err(format!("unimplemented {:x}", opcode)),
157 }
158 }
159 0x60 | 0x70 => {
160 // push
161 let n = (opcode - 0x5f) as usize;
162 self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
163 self.pc += 1 + n;
164 }
165 0x80 => {
166 // 0x8x dup
167 let l = self.stack.len();
168 if opcode > 0x7f {
169 self.stack.push(self.stack[l - (opcode - 0x7f) as usize]);
170 } else {
171 self.stack.push(self.stack[(0x7f - opcode) as usize]);
172 }
173 self.pc += 1;
174 }
175 0x90 => {
176 // 0x9x swap
177 let l = self.stack.len();
178 let pos;
179 if opcode > 0x8e {
180 pos = l - (opcode - 0x8e) as usize;
181 } else {
182 pos = (0x8e - opcode) as usize;
183 }
184 self.stack.swap(pos, l - 1);
185 self.pc += 1;
186 }
187 0xf0 => {
188 if opcode == 0xf3 {
189 let pos_to_return = u256::u256_to_u64(self.pop()?) as usize;
190 let len_to_return = u256::u256_to_u64(self.pop()?) as usize;
191 return Ok(self.mem[pos_to_return..pos_to_return + len_to_return].to_vec());
192 }
193 }
194 _ => {
195 return Err(format!("unimplemented {:x}", opcode));
196 }
197 }
198 self.gas -= self.opcodes.get(&opcode).unwrap().gas;
199 }
200 Ok(Vec::new())
201 }
202}
203pub fn vec_u8_to_hex(bytes: Vec<u8>) -> String {
204 let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
205 strs.join("")
206}