├── .gitignore ├── .travis.yml ├── README.md ├── Cargo.toml ├── LICENSE └── src ├── json.rs ├── trie.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minimal EVM in Rust 2 | 3 | [![Build Status](https://travis-ci.org/joelburget/evm-rust.svg?branch=master)](https://travis-ci.org/joelburget/evm-rust) 4 | 5 | So far this is a very elaborate way to do simple arithmetic. I'd eventually like to be able to execute transactions. I don't care about connecting to the Ethereum mainnet. 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "evm" 3 | version = "0.1.0" 4 | authors = ["Joel Burget "] 5 | license = "Apache-2.0" 6 | repository = "https://github.com/joelburget/evm-rust" 7 | 8 | [dependencies] 9 | num = "0.1" 10 | bigint = "4.2.0" 11 | sha3 = "0.7.2" 12 | nibble_vec = "0.0.4" 13 | digest = "0.7" 14 | data-encoding = "2.1.0" 15 | serde = "1.0" 16 | serde_derive = "1.0" 17 | serde_json = "1.0" 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Joel Burget 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /src/json.rs: -------------------------------------------------------------------------------- 1 | 2 | pub mod json { 3 | use bigint::uint::U256; 4 | use num::BigUint; 5 | use Address; 6 | use K256; 7 | use Stack; 8 | use FrameState; 9 | use VM; 10 | use Env; 11 | use Header; 12 | use Block; 13 | use std::fs::File; 14 | use ::serde_json; 15 | use std::num::ParseIntError; 16 | use std::str::FromStr; 17 | use std::io::Read; 18 | use std::convert::From; 19 | use std::convert::AsMut; 20 | 21 | 22 | pub fn load_test(filename: &str) -> (VM,VM) { 23 | let mut f = File::open(filename).expect("Could not find file"); 24 | let mut test_json = String::new(); 25 | f.read_to_string(&mut test_json).expect("Error reading file"); 26 | 27 | let parsed_test: Test = serde_json::from_str(&test_json).unwrap(); 28 | (init_vm(&parsed_test), final_vm(&parsed_test)) 29 | } 30 | 31 | /// These structs represent the test format described in 32 | /// http://ethereum-tests.readthedocs.io/en/latest/test_types/vm_tests.html 33 | 34 | #[derive(Deserialize)] 35 | struct Test { 36 | _info: serde_json::Value, 37 | env: TestEnv, 38 | pre: serde_json::Value, 39 | exec: TestExec, 40 | gas: String, //GAS REMAINING AT END OF EXECUTION 41 | logs: String, 42 | out: String, 43 | post: serde_json::Value, 44 | callcreates: serde_json::Value, 45 | } 46 | 47 | #[derive(Deserialize)] 48 | struct TestEnv { 49 | currentCoinbase: String, 50 | currentDifficulty: String, 51 | currentGasLimit: String, 52 | currentNumber: String, 53 | currentTimestamp: String, 54 | //XXX previousHash: String, 55 | } 56 | 57 | #[derive(Deserialize)] 58 | struct TestExec { 59 | address: String, 60 | origin: String, 61 | caller: String, 62 | value: String, 63 | data: String, 64 | code: String, 65 | gasPrice: String, 66 | gas: String, 67 | } 68 | 69 | #[derive(Deserialize)] 70 | struct TestAccount { 71 | balance: String, 72 | nonce: String, 73 | code: String, 74 | storage: String, 75 | } 76 | 77 | #[derive(Deserialize)] 78 | struct Test1 { 79 | add0: Test, 80 | } 81 | 82 | fn hexstr_to_vec(v: &str) -> Vec { 83 | let v_bytes = &v.as_bytes()[2..]; 84 | v_bytes.to_vec() 85 | } 86 | 87 | fn hexstr_to_address(addr: &str) -> Address { 88 | let addr_bytes = &addr.as_bytes()[2..]; 89 | Address(clone_into_array(addr_bytes)) 90 | } 91 | 92 | fn hexstr_to_u256(string: &str) -> U256 { 93 | let str_arr: [u8; 32] = clone_into_array(&string.as_bytes()[2..]); 94 | From::from(str_arr) 95 | } 96 | 97 | //fn hexstr_to_biguint(biguint: &str) -> BigUint { 98 | // let biguint_bytes = &biguint.as_bytes()[2..]; 99 | // from_bytes_be(biguint_bytes) 100 | //} 101 | 102 | // Found at https://stackoverflow.com/questions/25428920/how-to-get-a-slice-as-an-array-in-rust 103 | fn clone_into_array(slice: &[T]) -> A 104 | where A: Sized + Default + AsMut<[T]>, 105 | T: Clone 106 | { 107 | let mut a = Default::default(); 108 | >::as_mut(&mut a).clone_from_slice(slice); 109 | a 110 | } 111 | 112 | //NEED TO WIRE THESE VALS INTO THE VM: 113 | //unused from Test: pre, post, gas (at end), logs, out, callcreates 114 | //unused from TestEnv: currentCoinbase 115 | //unused from TestAccount: all (need to use pre/post) 116 | 117 | //The initial VM state for a test 118 | fn init_vm(test: &Test) -> VM { 119 | VM { 120 | result: None, 121 | state: FrameState { 122 | code: hexstr_to_vec(&test.exec.code), 123 | gas_available: hexstr_to_u256(&test.exec.gas), 124 | pc: 0, 125 | memory: Vec::new(), 126 | active_words: U256::zero(), 127 | stack: Stack::new(), 128 | }, 129 | env: Env { 130 | owner: hexstr_to_address(&test.exec.address), 131 | origin: hexstr_to_address(&test.exec.origin), 132 | gas_price: hexstr_to_u256(&test.exec.gasPrice), 133 | data: hexstr_to_vec(&test.exec.data), 134 | caller: hexstr_to_address(&test.exec.caller), 135 | transaction_value: hexstr_to_u256(&test.exec.value), 136 | code: hexstr_to_vec(&test.exec.code), 137 | header: Header {}, 138 | depth: 0, 139 | }, 140 | //XXX - This can be sorted out once the BigUint vs U256 thing is figured out 141 | block: Block { 142 | beneficiary: Address([0;20]), 143 | difficulty: U256::one(), 144 | number: U256::one(), 145 | gas_limit: U256::one(), 146 | timestamp: U256::one(), 147 | } 148 | } 149 | } 150 | 151 | //What the final VM state of a test should be 152 | fn final_vm(test: &Test) -> VM { 153 | VM { 154 | result: None, 155 | state: FrameState { 156 | code: hexstr_to_vec(&test.exec.code), 157 | gas_available: hexstr_to_u256(&test.gas), 158 | pc: 0, //XXX this is not tracked in the json tests so we should just default to the end PC 159 | memory: Vec::new(), //XXX 160 | active_words: U256::zero(), //XXX 161 | stack: Stack::new(), //XXX again, not tracked in the json 162 | }, 163 | env: Env { 164 | owner: hexstr_to_address(&test.exec.address), 165 | origin: hexstr_to_address(&test.exec.origin), 166 | gas_price: hexstr_to_u256(&test.exec.gasPrice), 167 | data: hexstr_to_vec(&test.exec.data), 168 | caller: hexstr_to_address(&test.exec.caller), 169 | transaction_value: hexstr_to_u256(&test.exec.value), 170 | code: hexstr_to_vec(&test.exec.code), 171 | header: Header {}, 172 | depth: 0, 173 | }, 174 | //XXX - This can be sorted out once the BigUint vs U256 thing is figured out 175 | block: Block { 176 | beneficiary: Address([0;20]), 177 | difficulty: U256::one(), 178 | number: U256::one(), 179 | gas_limit: U256::one(), 180 | timestamp: U256::one(), 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/trie.rs: -------------------------------------------------------------------------------- 1 | macro_rules! no_children { 2 | () => ([ 3 | None, None, None, None, 4 | None, None, None, None, 5 | None, None, None, None, 6 | None, None, None, None 7 | ]) 8 | } 9 | 10 | pub mod trie { 11 | use bigint::uint::U256; 12 | use nibble_vec::NibbleVec; 13 | use num::traits::WrappingAdd; 14 | use num::{FromPrimitive}; 15 | use sha3::{Digest, Keccak256}; 16 | use self::TrieNode::*; 17 | use core::cmp::min; 18 | use core::ops::Deref; 19 | use data_encoding::HEXLOWER; 20 | 21 | #[derive(Debug, Clone)] 22 | pub enum TrieNode { 23 | /// A two-item structure: 24 | /// * the nibbles in the key not already accounted for by the accumulation of keys and 25 | /// branches traversed from the root 26 | /// - hex-prefix encoding is used with the second parameter *true* 27 | /// * data at the leaf 28 | Leaf { 29 | nibbles: NibbleVec, 30 | data: NibbleVec, 31 | }, 32 | /// A two-item structure: 33 | /// * a series of nibbles of size greater than one that are shared by at least two distinct 34 | /// keys past the accumulation of nibbles keys and branches as traversed from the root 35 | /// - hex-prefix encoding is used with the second parameter *false* 36 | /// * data at the extension 37 | Extension { 38 | nibbles: NibbleVec, 39 | subtree: Box, 40 | }, 41 | /// A 17-item structure whose first sixteen items correspond to each of the sixteen 42 | /// possible nibble values for the keys at this point in their traversal. The 17th item is 43 | /// used in the case of this being a terminator node and thus a key being ended at this 44 | /// point in its traversal. 45 | Branch { 46 | children: [Option>; 16], 47 | data: Option, 48 | }, 49 | } 50 | 51 | pub struct RlpEncoded(Vec); 52 | 53 | impl RlpEncoded { 54 | pub fn to_vec(self) -> Vec { 55 | match self { 56 | RlpEncoded(vec) => vec 57 | } 58 | } 59 | } 60 | 61 | impl Rlp for RlpEncoded { 62 | fn rlp(&self) -> RlpEncoded { 63 | match self { 64 | &RlpEncoded(ref vec) => RlpEncoded(vec.clone()) 65 | } 66 | } 67 | } 68 | 69 | fn find_prefix(p1: &NibbleVec, p2: &NibbleVec) -> (NibbleVec, NibbleVec, NibbleVec) { 70 | // find common prefix 71 | let iter_count = min(p1.len(), p2.len()); 72 | let mut prefix_len: usize = 0; 73 | 74 | for i in 0..iter_count { 75 | if p1.get(i) != p2.get(i) { 76 | break; 77 | } 78 | prefix_len += 1; 79 | } 80 | 81 | ( 82 | slice(&p1, 0, prefix_len), 83 | slice(&p1, prefix_len, p1.len()), 84 | slice(&p2, prefix_len, p2.len()), 85 | ) 86 | } 87 | 88 | fn maybe_extend(prefix: NibbleVec, node: TrieNode) -> TrieNode { 89 | if !prefix.is_empty() { 90 | Extension { 91 | nibbles: prefix, 92 | subtree: Box::new(node), 93 | } 94 | } else { 95 | node 96 | } 97 | } 98 | 99 | fn two_branch(prefix: NibbleVec, 100 | k1: NibbleVec, v1: NibbleVec, 101 | k2: NibbleVec, v2: NibbleVec) -> TrieNode { 102 | let mut branch = Branch { 103 | children: no_children![], 104 | data: None, 105 | }; 106 | branch.update(k1, v1); 107 | branch.update(k2, v2); 108 | maybe_extend(prefix, branch) 109 | } 110 | 111 | impl TrieNode { 112 | pub fn lookup(&self, path: NibbleVec) -> Option> { 113 | match self { 114 | &Leaf { ref nibbles, ref data } => { 115 | if path != *nibbles { 116 | None 117 | } else { 118 | Some(data.clone().into_bytes()) 119 | } 120 | } 121 | 122 | &Extension { ref nibbles, ref subtree } => { 123 | let (prefix, nibbles_extra, path_extra) = find_prefix(nibbles, &path); 124 | 125 | // the path passed in should be at least as long as the extension nibbles. 126 | // return None if not 127 | if !nibbles_extra.is_empty() { 128 | None 129 | } else { 130 | subtree.lookup(path_extra) 131 | } 132 | } 133 | 134 | &Branch { ref children, ref data } => { 135 | if path.is_empty() { 136 | data.clone().map(|x| x.into_bytes()) 137 | } else { 138 | let (hd, tl) = nibble_head_tail(path); 139 | match children[hd as usize] { 140 | None => None, 141 | Some(ref x) => x.lookup(tl), 142 | } 143 | } 144 | } 145 | } 146 | } 147 | 148 | pub fn update(&mut self, path: NibbleVec, value: NibbleVec) { 149 | let mut result: Option = None; 150 | match self { 151 | &mut Leaf { ref mut nibbles, ref mut data } => { 152 | let (prefix, old_extra, new_extra) = find_prefix(nibbles, &path); 153 | 154 | if old_extra.len() == 0 && new_extra.len() == 0 { 155 | result = Some(Leaf { 156 | nibbles: prefix, 157 | data: value, 158 | }); 159 | 160 | } else { 161 | // otherwise we create an extension with prefix pointing to a branch 162 | result = Some(two_branch( 163 | prefix, 164 | old_extra, data.clone(), 165 | new_extra, value 166 | )); 167 | } 168 | }, 169 | 170 | &mut Extension { ref mut nibbles, ref mut subtree } => { 171 | let (prefix, old_extra, new_extra) = find_prefix(nibbles, &path); 172 | if old_extra.len() == 0 { 173 | // insert old subtree and new data as a branch 174 | let mut subtree = subtree.deref().clone(); // TODO: don't clone 175 | subtree.update(new_extra, value); 176 | result = Some(maybe_extend(prefix, *subtree)); 177 | } else { 178 | // the new key we're inserting bottoms out here 179 | result = Some(two_branch( 180 | prefix, 181 | old_extra, nibbles.clone(), 182 | new_extra, value 183 | )); 184 | } 185 | }, 186 | 187 | &mut Branch { ref mut children, ref mut data } => { 188 | let mut children = children.clone(); 189 | if path.is_empty() { 190 | result = Some(Branch { 191 | children, 192 | data: Some(value), 193 | }); 194 | } else { 195 | let (hd, tl) = nibble_head_tail(path); 196 | match children[hd as usize] { 197 | None => { 198 | children[hd as usize] = Some(Box::new(Leaf { 199 | nibbles: tl, 200 | data: value, 201 | })); 202 | }, 203 | Some(ref mut child) => { 204 | child.update(tl, value); 205 | }, 206 | } 207 | result = Some(Branch { 208 | children, 209 | data: data.clone(), 210 | }); 211 | } 212 | }, 213 | }; 214 | 215 | match result { 216 | None => {}, 217 | Some(result) => { *self = result; }, 218 | } 219 | } 220 | } 221 | 222 | fn rlp_reference(node: &TrieNode) -> RlpEncoded { 223 | match node { 224 | &Leaf{..} => node.rlp(), 225 | &Extension{..} => node.rlp(), 226 | &Branch{..} => { 227 | let mut hasher = Keccak256::default(); 228 | hasher.input(node.deref().rlp().to_vec().as_slice()); 229 | let subtree_hash: &[u8] = &hasher.result(); 230 | Vec::from(subtree_hash).rlp() 231 | } 232 | } 233 | } 234 | 235 | impl <'a>Rlp for &'a TrieNode { 236 | fn rlp(&self) -> RlpEncoded { 237 | match *self { 238 | &Leaf { ref nibbles, ref data } => { 239 | vec![ 240 | hex_prefix_encode_nibbles(nibbles, true), 241 | data.clone().into_bytes().rlp(), 242 | ].rlp() 243 | }, 244 | 245 | &Extension { ref nibbles, ref subtree } => { 246 | vec![ 247 | hex_prefix_encode_nibbles(nibbles, false), 248 | rlp_reference(subtree) 249 | ].rlp() 250 | }, 251 | 252 | &Branch { ref children, ref data } => { 253 | let mut v: Vec = Vec::new(); 254 | 255 | for child in children.to_vec().iter() { 256 | v.push(match *child { 257 | None => RlpEncoded(vec![0x80]), 258 | Some(ref data) => rlp_reference(data), 259 | }); 260 | } 261 | 262 | v.push(match *data { 263 | None => RlpEncoded(vec![0x80]), 264 | Some(ref data) => data.clone().into_bytes().rlp(), 265 | }); 266 | 267 | v.rlp() 268 | }, 269 | } 270 | } 271 | } 272 | 273 | #[derive(Clone, Debug)] 274 | pub struct Trie { 275 | node: TrieNode, 276 | is_empty: bool, 277 | } 278 | 279 | pub trait Rlp { 280 | fn rlp(&self) -> RlpEncoded; 281 | } 282 | 283 | pub fn rlp_encode_list(lst: Vec) -> RlpEncoded { 284 | lst.rlp() 285 | } 286 | 287 | // alternate name: rlp_encode_str 288 | impl Rlp for Vec { 289 | /// R_b 290 | fn rlp(&self) -> RlpEncoded { 291 | let bytes = self; 292 | let len = bytes.len(); 293 | let mut ret: Vec; 294 | if len == 1 && bytes[0] < 128 { 295 | ret = Vec::new(); 296 | } else if len < 56 { 297 | let len8 = len as u8; 298 | ret = vec![128 + len8]; 299 | } else { 300 | // length of the string 301 | let mut be_buf: [u8; 32] = [0; 32]; // TODO: big enough? 302 | 303 | // length in bytes of the length of the string in binary form 304 | U256::from(len).to_big_endian(&mut be_buf); 305 | // let be_len_bytes = be_buf.len() as u8; 306 | let be_len_bytes = be_buf 307 | .iter() 308 | .skip_while(|x| **x == 0) 309 | .cloned() 310 | .collect::>(); 311 | 312 | // length in bytes of th elength of the string in binary form 313 | let be_len_bytes_len = be_len_bytes.len() as u8; 314 | 315 | ret = vec![183 + be_len_bytes_len]; 316 | ret.extend(be_len_bytes.as_slice()); 317 | } 318 | 319 | ret.extend(bytes); 320 | RlpEncoded(ret) 321 | } 322 | } 323 | 324 | // alternate name: rlp_encode_list 325 | impl Rlp for Vec 326 | where T: Rlp { 327 | /// R_l 328 | fn rlp(&self) -> RlpEncoded { 329 | let bytes: Vec = self 330 | .iter() 331 | .map(|x| x.rlp().to_vec()) 332 | .collect::>>() 333 | .concat(); 334 | let len = bytes.len(); 335 | 336 | let mut prefix: Vec; 337 | if len < 56 { 338 | let len8 = len as u8; 339 | prefix = vec![192 + len8]; 340 | } else { 341 | let mut be_buf: [u8; 32] = [0; 32]; // TODO: big enough? bigint forces length 32? 342 | 343 | // length in bytes of the length of the string in binary form 344 | U256::from(len).to_big_endian(&mut be_buf); 345 | let be_len_bytes = be_buf 346 | .into_iter() 347 | .skip_while(|x| **x == 0) 348 | .cloned() 349 | .collect::>(); 350 | 351 | let be_len_bytes_len = be_len_bytes.len() as u8; 352 | prefix = vec![247 + be_len_bytes_len]; 353 | prefix.extend(be_len_bytes.as_slice()); 354 | } 355 | prefix.extend(bytes); 356 | RlpEncoded(prefix) 357 | } 358 | } 359 | 360 | fn nibble_head_tail(mut nibbles: NibbleVec) -> (u8, NibbleVec) { 361 | let tl = nibbles.split(1); 362 | (nibbles.get(0), tl) 363 | } 364 | 365 | fn slice(nibbles: &NibbleVec, start: usize, end: usize) -> NibbleVec { 366 | // |----|---------|-----| 367 | let mut clone = nibbles.clone(); 368 | 369 | // |----|---------| 370 | clone.split(end); 371 | 372 | // |---------| 373 | let ret = clone.split(start); 374 | ret 375 | } 376 | 377 | // HP 378 | fn hex_prefix_encode_nibbles(nibbles: &NibbleVec, t: bool) -> RlpEncoded { 379 | let len = nibbles.len(); 380 | let f = u8::from_usize(if t { 2 } else { 0 }) 381 | .expect("a 0 or a 2 couldn't fit into 4 bits!"); 382 | let prefix: u8; 383 | if len % 2 == 0 { 384 | prefix = f; 385 | } else { 386 | prefix = f.wrapping_add(1); 387 | } 388 | 389 | let mut ret = NibbleVec::new(); 390 | ret.push(prefix); 391 | 392 | // if even, insert extra nibble 393 | if len & 1 == 0 { ret.push(0); } 394 | 395 | ret.join(nibbles).into_bytes().rlp() 396 | } 397 | 398 | impl Trie { 399 | pub fn new() -> Trie { 400 | // TODO: can we move this to a constant? 401 | let emptyNode: TrieNode = Leaf { 402 | nibbles: NibbleVec::new(), 403 | data: NibbleVec::new(), 404 | }; 405 | 406 | return Trie { node: emptyNode, is_empty: true }; 407 | } 408 | 409 | pub fn insert(&mut self, path: NibbleVec, value: NibbleVec) { 410 | if self.is_empty { 411 | self.node = Leaf { 412 | nibbles: path, 413 | data: value, 414 | }; 415 | self.is_empty = false; 416 | } else { 417 | self.node.update(path, value); 418 | } 419 | } 420 | 421 | pub fn lookup(&self, path: NibbleVec) -> Option> { 422 | self.node.lookup(path) 423 | } 424 | 425 | pub fn hash(&self) -> U256 { 426 | let mut hasher = Keccak256::default(); 427 | hasher.input(self.rlp_node().to_vec().as_slice()); 428 | let out: &[u8] = &hasher.result(); 429 | U256::from(out) 430 | } 431 | 432 | pub fn rlp_node(&self) -> RlpEncoded { 433 | (&self.node).rlp() 434 | } 435 | 436 | pub fn hex_root(&self) -> String { 437 | let mut buf = [0; 32]; 438 | self.hash().to_big_endian(&mut buf); 439 | return HEXLOWER.encode(&buf); 440 | } 441 | } 442 | } 443 | 444 | #[cfg(test)] 445 | mod tests { 446 | use nibble_vec::NibbleVec; 447 | use trie::trie::{Trie,Rlp}; 448 | use data_encoding::HEXLOWER; 449 | 450 | #[test] 451 | fn insertion() { 452 | let t = &mut Trie::new(); 453 | // t.insert(NibbleVec::new(), vec![1,2,3]); 454 | } 455 | 456 | fn hex_to_nibbles(str: &[u8]) -> NibbleVec { 457 | NibbleVec::from_byte_vec(HEXLOWER.decode(str).unwrap()) 458 | } 459 | 460 | fn vec_str_to_nibbles(v: Vec<&str>) -> NibbleVec { 461 | let v: Vec> = v.iter().map(|x| Vec::from(x.as_bytes())).collect::>(); 462 | let v: Vec = v.rlp().to_vec(); 463 | NibbleVec::from_byte_vec(v) 464 | } 465 | 466 | #[test] 467 | fn matches_blog() { 468 | let t = &mut Trie::new(); 469 | 470 | println!("exercise 1\n"); 471 | // >>> state.root_node 472 | // [' \x01\x01\x02', '\xc6\x85hello'] 473 | // >>> rlp.encode(state.root_node) 474 | // '\xcd\x84 \x01\x01\x02\x87\xc6\x85hello' 475 | t.insert(hex_to_nibbles(b"010102"), vec_str_to_nibbles(vec!["hello"])); 476 | assert_eq!(t.hex_root(), "15da97c42b7ed2e1c0c8dab6a6d7e3d9dc0a75580bbc4f1f29c33996d1415dcc"); 477 | 478 | // these tests use this as a starting point 479 | let mut t2b = t.clone(); 480 | let mut t2c = t.clone(); 481 | let mut t2d = t.clone(); 482 | let mut t3 = t.clone(); 483 | 484 | println!("exercise 2\n"); 485 | // make an entry with the same key 486 | t.insert(hex_to_nibbles(b"010102"), vec_str_to_nibbles(vec!["hellothere"])); 487 | assert_eq!(t.hex_root(), "05e13d8be09601998499c89846ec5f3101a1ca09373a5f0b74021261af85d396"); 488 | 489 | println!("exercise 2b\n"); 490 | // make an entry with almost the same key but a different final nibble 491 | t2b.insert(hex_to_nibbles(b"010103"), vec_str_to_nibbles(vec!["hellothere"])); 492 | assert_eq!(t2b.hex_root(), "b5e187f15f1a250e51a78561e29ccfc0a7f48e06d19ce02f98dd61159e81f71d"); 493 | 494 | println!("exercise 2c\n"); 495 | t2c.insert(hex_to_nibbles(b"0101"), vec_str_to_nibbles(vec!["hellothere"])); 496 | assert_eq!(t2c.hex_root(), "f3e46945b73ef862d59850a8e1a73ef736625dd9a02bed1c9f2cc3ff4cd798b3"); 497 | 498 | println!("exercise 2d\n"); 499 | t2d.insert(hex_to_nibbles(b"01010257"), vec_str_to_nibbles(vec!["hellothere"])); 500 | assert_eq!(t2d.hex_root(), "dfd000b4b04811e7e59f1648f887bd56c16e4c047d6267793cf0eacf4b035c34"); 501 | 502 | println!("exercise 3\n"); 503 | 504 | // t.insert(hex_to_nibbles(b"010102"), vec_str_to_nibbles(vec!["hello"])); 505 | t3.insert(hex_to_nibbles(b"01010255"), vec_str_to_nibbles(vec!["hellothere"])); 506 | assert_eq!(t3.hex_root(), "17fe8af9c6e73de00ed5fd45d07e88b0c852da5dd4ee43870a26c39fc0ec6fb3"); 507 | t3.insert(hex_to_nibbles(b"01010257"), vec_str_to_nibbles(vec!["jimbojones"])); 508 | assert_eq!(t3.hex_root(), "fcb2e3098029e816b04d99d7e1bba22d7b77336f9fe8604f2adfb04bcf04a727"); 509 | 510 | println!("exercise 4\n"); 511 | 512 | assert_eq!( 513 | t2b.lookup(hex_to_nibbles(b"010102")), 514 | Some(vec![Vec::from("hello".as_bytes())].rlp().to_vec()) 515 | ); 516 | assert_eq!( 517 | t2b.lookup(hex_to_nibbles(b"010103")), 518 | Some(vec![Vec::from("hellothere".as_bytes())].rlp().to_vec()) 519 | ); 520 | 521 | assert_eq!( 522 | t3.lookup(hex_to_nibbles(b"010102")), 523 | Some(vec![Vec::from("hello".as_bytes())].rlp().to_vec()) 524 | ); 525 | assert_eq!( 526 | t3.lookup(hex_to_nibbles(b"01010255")), 527 | Some(vec![Vec::from("hellothere".as_bytes())].rlp().to_vec()) 528 | ); 529 | assert_eq!( 530 | t3.lookup(hex_to_nibbles(b"01010257")), 531 | Some(vec![Vec::from("jimbojones".as_bytes())].rlp().to_vec()) 532 | ); 533 | } 534 | } 535 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_derive; 3 | extern crate serde; 4 | extern crate serde_json; 5 | extern crate bigint; 6 | extern crate core; 7 | extern crate digest; 8 | extern crate nibble_vec; 9 | extern crate num; 10 | extern crate sha3; 11 | extern crate data_encoding; 12 | 13 | pub mod trie; 14 | pub mod json; 15 | 16 | use core::clone::Clone; 17 | use core::ops::{Add,BitAnd,BitOr,BitXor,Index,IndexMut,Mul,Not,Sub}; 18 | use std::cmp::max; 19 | use bigint::uint::U256; 20 | use num::BigUint; 21 | use std::convert::From; 22 | 23 | const homestead: u32 = 1150000; 24 | 25 | type Instruction = u8; 26 | 27 | #[derive(PartialEq, Clone)] 28 | pub struct K256(U256); 29 | 30 | #[derive(PartialEq, Clone)] 31 | pub struct Address([u8; 20]); 32 | 33 | #[derive(PartialEq, Clone)] 34 | pub enum VMResult { 35 | VmFailure, 36 | VmSuccess, 37 | } 38 | 39 | #[derive(Clone)] 40 | pub struct S256(U256); 41 | 42 | 43 | // Basic version of signed semantics. Kind of gross because 44 | // most two's complement arithmetic is the same for signed/unsigned 45 | // so seems unnecessary to implement every op for S256. But on the other 46 | // hand also annoying to keep wrapping/unwrapping. 47 | impl S256 { 48 | 49 | fn to_u256(&self) -> U256 { 50 | self.0 51 | } 52 | 53 | fn abs(&self) -> U256 { 54 | let num = self.0; 55 | if num.bit(255) { 56 | !num + U256::one() 57 | } else { 58 | num 59 | } 60 | } 61 | 62 | fn invert(&self) -> S256 { 63 | let num = self.0; 64 | S256(!num + U256::one()) 65 | } 66 | 67 | fn sign(&self) -> bool { 68 | self.0.bit(255) 69 | } 70 | 71 | } 72 | 73 | #[derive(PartialEq, Clone)] 74 | pub struct Stack(Vec); 75 | 76 | impl Stack { 77 | fn new() -> Stack { 78 | return Stack(Vec::new()); 79 | } 80 | 81 | fn push(&mut self, value: U256) { 82 | self.0.push(value); 83 | } 84 | 85 | fn pop(&mut self, times: usize) { 86 | for _i in 0..times { 87 | self.0.pop(); 88 | } 89 | } 90 | 91 | fn apply_ternary_op(&mut self, op: F) 92 | where F: Fn(U256, U256, U256) -> U256, 93 | { 94 | let result = op(self[0], self[1], self[2]); 95 | self.pop(3); 96 | self.push(result); 97 | } 98 | 99 | fn apply_binary_op(&mut self, op: F) 100 | where F: Fn(U256, U256) -> U256, 101 | { 102 | let result = op(self[0], self[1]); 103 | self.pop(2); 104 | self.push(result); 105 | } 106 | 107 | fn apply_unary_op(&mut self, op: F) 108 | where F: Fn(U256) -> U256, 109 | { 110 | let result = op(self[0]); 111 | self[0] = result; 112 | } 113 | } 114 | 115 | impl Index for Stack { 116 | type Output = U256; 117 | 118 | fn index<'a>(&'a self, index: usize) -> &'a U256 { 119 | let veclen = self.0.len(); 120 | return &self.0[veclen - index - 1]; 121 | } 122 | } 123 | 124 | impl IndexMut for Stack { 125 | fn index_mut(&mut self, index: usize) -> &mut U256 { 126 | let veclen = self.0.len(); 127 | return &mut self.0[veclen - index - 1]; 128 | } 129 | } 130 | 131 | // Mostly from 9.4.1: Machine State 132 | #[derive(PartialEq, Clone)] 133 | pub struct FrameState { 134 | // contract 135 | code: Vec, // XXX is code part of FrameState or Env? 136 | gas_available: U256, 137 | pc: usize, // U256, 138 | memory: Vec, 139 | active_words: U256, 140 | stack: Stack, 141 | // memorySize 142 | // calldata 143 | // callvalue 144 | // caller 145 | } 146 | 147 | impl FrameState { 148 | pub fn m_store(&mut self, loc: usize, word: U256) { 149 | let mut bytes: [u8; 32] = [0; 32]; 150 | word.to_big_endian(&mut bytes); 151 | 152 | for _i in self.memory.len() .. loc + 32 { 153 | self.memory.push(0); 154 | } 155 | 156 | for (i, byte) in bytes.iter().enumerate() { 157 | self.memory[loc + i] = *byte; 158 | } 159 | self.active_words = self.active_words.max(U256::from((loc + 32) / 32)); 160 | } 161 | 162 | pub fn m_store8(&mut self, loc: usize, byte: u8) { 163 | for _i in self.memory.len() .. loc + 1 { 164 | self.memory.push(0); 165 | } 166 | 167 | self.memory[loc] = byte; 168 | self.active_words = self.active_words.max(U256::from((loc + 1) / 32)); 169 | } 170 | 171 | pub fn m_load(&mut self, loc: usize) -> U256 { 172 | if self.memory.len() < loc + 32 { 173 | self.memory.resize(loc + 32, 0); 174 | } 175 | 176 | self.active_words = self.active_words.max(U256::from((loc + 32) / 32)); 177 | return U256::from_big_endian(&self.memory[loc..loc+32]); 178 | } 179 | } 180 | 181 | #[derive(PartialEq, Clone)] 182 | pub struct AccountState { 183 | nonce: u32, 184 | balance: u32, 185 | storage_root: K256, 186 | code_hash: K256, 187 | } 188 | 189 | #[derive(PartialEq, Clone)] 190 | pub struct TransactionCommon { 191 | nonce: u64, 192 | gas_price: U256, 193 | gas_limit: U256, 194 | to: Address, 195 | value: U256, 196 | v: U256, 197 | r: U256, 198 | s: U256, 199 | } 200 | 201 | #[derive(PartialEq, Clone)] 202 | pub enum Transaction { 203 | CreationTransaction { common: TransactionCommon, init: Option> }, 204 | CallTransaction { common: TransactionCommon, data: Vec }, 205 | } 206 | 207 | struct Bloom([u8; 256]); 208 | 209 | impl PartialEq for Bloom { 210 | fn eq(&self, &Bloom(other): &Bloom) -> bool { 211 | // https://stackoverflow.com/a/23149538/383958 212 | self.0.iter().zip(other.iter()).all(|(a,b)| a == b) 213 | } 214 | } 215 | 216 | impl Clone for Bloom { 217 | fn clone(&self) -> Bloom { Bloom(self.0) } 218 | } 219 | 220 | // for now, filter down to only the fields we actually use 221 | #[derive(PartialEq, Clone)] 222 | pub struct Block { 223 | // parent_hash: K256, 224 | // ommers_hash: K256, 225 | beneficiary: Address, 226 | // state_root: K256, 227 | // transactions_root: K256, 228 | // receipts_root: K256, 229 | // logs_bloom: Bloom, 230 | difficulty: U256, 231 | number: U256, 232 | gas_limit: U256, 233 | // gas_used: U256, 234 | timestamp: U256, 235 | // extra_data: Vec, 236 | // mix_hash: K256, 237 | // nonce: u64, 238 | } 239 | 240 | #[derive(PartialEq, Clone)] 241 | pub struct Log { 242 | address: Address, 243 | topics: Vec, 244 | data: Vec, 245 | block_number: u64, 246 | tx_hash: K256, 247 | tx_index: u32, 248 | block_hash: K256, 249 | index: u32, 250 | removed: bool, 251 | } 252 | 253 | #[derive(PartialEq, Clone)] 254 | pub struct TransactionReceipt { 255 | // state: 256 | gas_used: U256, 257 | logs: Vec, 258 | bloom: Bloom, 259 | } 260 | 261 | #[derive(PartialEq, Clone)] 262 | pub struct Contract { 263 | // callerAddress: Address, 264 | // caller 265 | } 266 | 267 | #[derive(PartialEq, Clone)] 268 | pub struct Header {} 269 | 270 | #[derive(PartialEq, Clone)] 271 | pub struct Env { 272 | /// I_a, the address of the account which owns the code that is executing 273 | owner: Address, 274 | 275 | /// I_o, the sender address of the transaction that originated this execution 276 | origin: Address, 277 | 278 | /// I_p: the price of gas in the transaction that originated this execution 279 | gas_price: U256, // XXX also in TransactionCommon 280 | 281 | /// I_d: the byte array that is the input data to this execution; if the execution agent is a 282 | /// transaction, this would be the transaction data 283 | data: Vec, 284 | 285 | /// I_s: the address of the account which caused the code to be executing; if the execution 286 | /// agent is a transaction this would be the transaction sender 287 | caller: Address, 288 | 289 | /// I_v, the value, in Wei, passed to this account as part of the same procedure as execution; 290 | /// if the execution agent is a transaction, this would be the transaction value 291 | transaction_value: U256, 292 | 293 | /// I_b, the byte array that is the machine code to be executed 294 | code: Vec, 295 | 296 | /// I_H, the block header of the present block 297 | header: Header, 298 | 299 | /// I_e: the depth of the present message-call or contract-creation (ie the number of CALLs of 300 | /// CREATEs being executed at present) 301 | depth: u16, 302 | } 303 | 304 | #[derive(PartialEq, Clone)] 305 | pub struct VM { 306 | result: Option, 307 | state: FrameState, 308 | // frames: Array, 309 | env: Env, 310 | block: Block, 311 | } 312 | 313 | // 0s: stop and arithmetic operations 314 | pub const STOP: u8 = 0x00; 315 | pub const ADD: u8 = 0x01; 316 | pub const MUL: u8 = 0x02; 317 | pub const SUB: u8 = 0x03; 318 | pub const DIV: u8 = 0x04; 319 | pub const SDIV: u8 = 0x05; 320 | pub const MOD: u8 = 0x06; 321 | pub const SMOD: u8 = 0x07; 322 | pub const ADDMOD: u8 = 0x08; 323 | pub const MULMOD: u8 = 0x09; 324 | pub const EXP: u8 = 0x0a; 325 | pub const SIGNEXTEND: u8 = 0x0b; 326 | 327 | // 10s: comparison & bitwise logic operations 328 | pub const LT: u8 = 0x10; 329 | pub const GT: u8 = 0x11; 330 | pub const SLT: u8 = 0x12; 331 | pub const SGT: u8 = 0x13; 332 | pub const EQ: u8 = 0x14; 333 | pub const ISZERO: u8 = 0x15; 334 | pub const AND: u8 = 0x16; 335 | pub const OR: u8 = 0x17; 336 | pub const XOR: u8 = 0x18; 337 | pub const NOT: u8 = 0x19; 338 | pub const BYTE: u8 = 0x1a; 339 | 340 | // 20s: sha3 341 | pub const SHA3: u8 = 0x20; 342 | 343 | // 30s: environmental information 344 | pub const ADDRESS: u8 = 0x30; 345 | pub const BALANCE: u8 = 0x31; 346 | pub const ORIGIN: u8 = 0x32; 347 | pub const CALLER: u8 = 0x33; 348 | pub const CALLVALUE: u8 = 0x34; 349 | pub const CALLDATALOAD: u8 = 0x35; 350 | pub const CALLDATASIZE: u8 = 0x36; 351 | pub const CALLDATACOPY: u8 = 0x37; 352 | pub const CODESIZE: u8 = 0x38; 353 | pub const CODECOPY: u8 = 0x39; 354 | pub const GASPRICE: u8 = 0x3a; 355 | pub const EXTCODESIZE: u8 = 0x3b; 356 | pub const EXTCODECOPY: u8 = 0x3c; 357 | 358 | // 40s: block information 359 | pub const BLOCKHASH: u8 = 0x40; 360 | pub const COINBASE: u8 = 0x41; 361 | pub const TIMESTAMP: u8 = 0x42; 362 | pub const NUMBER: u8 = 0x43; 363 | pub const DIFFICULTY: u8 = 0x44; 364 | pub const GASLIMIT: u8 = 0x45; 365 | 366 | // 50s: stack, memory, storage, and flow operations 367 | pub const POP: u8 = 0x50; 368 | pub const MLOAD: u8 = 0x51; 369 | pub const MSTORE: u8 = 0x52; 370 | pub const MSTORE8: u8 = 0x53; 371 | pub const JUMP: u8 = 0x54; 372 | pub const JUMPI: u8 = 0x55; 373 | pub const PC: u8 = 0x58; 374 | pub const MSIZE: u8 = 0x59; 375 | pub const GAS: u8 = 0x5a; 376 | pub const JUMPDEST: u8 = 0x5b; 377 | 378 | pub const PUSH1: u8 = 0x60; 379 | pub const PUSH2: u8 = 0x61; 380 | pub const PUSH3: u8 = 0x62; 381 | pub const PUSH4: u8 = 0x63; 382 | pub const PUSH5: u8 = 0x64; 383 | pub const PUSH6: u8 = 0x65; 384 | pub const PUSH7: u8 = 0x66; 385 | pub const PUSH8: u8 = 0x67; 386 | pub const PUSH9: u8 = 0x68; 387 | pub const PUSH10: u8 = 0x69; 388 | pub const PUSH11: u8 = 0x6a; 389 | pub const PUSH12: u8 = 0x6b; 390 | pub const PUSH13: u8 = 0x6c; 391 | pub const PUSH14: u8 = 0x6d; 392 | pub const PUSH15: u8 = 0x6e; 393 | pub const PUSH16: u8 = 0x6f; 394 | pub const PUSH17: u8 = 0x70; 395 | pub const PUSH18: u8 = 0x71; 396 | pub const PUSH19: u8 = 0x72; 397 | pub const PUSH20: u8 = 0x73; 398 | pub const PUSH21: u8 = 0x74; 399 | pub const PUSH22: u8 = 0x75; 400 | pub const PUSH23: u8 = 0x76; 401 | pub const PUSH24: u8 = 0x77; 402 | pub const PUSH25: u8 = 0x78; 403 | pub const PUSH26: u8 = 0x79; 404 | pub const PUSH27: u8 = 0x7a; 405 | pub const PUSH28: u8 = 0x7b; 406 | pub const PUSH29: u8 = 0x7c; 407 | pub const PUSH30: u8 = 0x7d; 408 | pub const PUSH31: u8 = 0x7e; 409 | pub const PUSH32: u8 = 0x7f; 410 | 411 | // 60s & 70s: push operations 412 | // 80s: duplication operations 413 | pub const DUP1: u8 = 0x80; 414 | pub const DUP2: u8 = 0x81; 415 | pub const DUP3: u8 = 0x82; 416 | pub const DUP4: u8 = 0x83; 417 | pub const DUP5: u8 = 0x84; 418 | pub const DUP6: u8 = 0x85; 419 | pub const DUP7: u8 = 0x86; 420 | pub const DUP8: u8 = 0x87; 421 | pub const DUP9: u8 = 0x88; 422 | pub const DUP10: u8 = 0x89; 423 | pub const DUP11: u8 = 0x8a; 424 | pub const DUP12: u8 = 0x8b; 425 | pub const DUP13: u8 = 0x8c; 426 | pub const DUP14: u8 = 0x8d; 427 | pub const DUP15: u8 = 0x8e; 428 | pub const DUP16: u8 = 0x8f; 429 | 430 | // 90s: exchange operations 431 | pub const SWAP1: u8 = 0x90; 432 | pub const SWAP2: u8 = 0x91; 433 | pub const SWAP3: u8 = 0x92; 434 | pub const SWAP4: u8 = 0x93; 435 | pub const SWAP5: u8 = 0x94; 436 | pub const SWAP6: u8 = 0x95; 437 | pub const SWAP7: u8 = 0x96; 438 | pub const SWAP8: u8 = 0x97; 439 | pub const SWAP9: u8 = 0x98; 440 | pub const SWAP10: u8 = 0x99; 441 | pub const SWAP11: u8 = 0x9a; 442 | pub const SWAP12: u8 = 0x9b; 443 | pub const SWAP13: u8 = 0x9c; 444 | pub const SWAP14: u8 = 0x9d; 445 | pub const SWAP15: u8 = 0x9e; 446 | pub const SWAP16: u8 = 0x9f; 447 | 448 | // a0s: logging operations 449 | 450 | // Should these be 256 bit or smaller? 451 | fn memory_expansion(s: U256, f: U256, l: U256) -> U256 { 452 | if l.is_zero() { s } else { max(s, (f + l) / U256::from(32)) } 453 | } 454 | 455 | fn bool_to_u256(b: bool) -> U256 { 456 | if b { U256::one() } else { U256::zero() } 457 | } 458 | 459 | fn addr_to_u256(&Address(bytes): &Address) -> U256 { 460 | return U256::from_big_endian(&bytes[0..20]); 461 | } 462 | 463 | fn big_to_u256(big: &BigUint) -> U256 { 464 | let bytes = big.to_bytes_be(); 465 | return U256::from_big_endian(&bytes); 466 | } 467 | 468 | pub enum InstructionResult { 469 | Normal, 470 | Halt, 471 | } 472 | 473 | impl VM { 474 | pub fn step(&mut self) -> InstructionResult { 475 | use InstructionResult::*; 476 | 477 | let pc = self.state.pc; 478 | let op = self.state.code[pc]; 479 | let state = &mut self.state; 480 | 481 | if op >= PUSH1 && op <= PUSH32 { 482 | let n = usize::from(op - PUSH1 + 1); 483 | let val1 = &state.code[pc+1..pc+n+1]; 484 | let val = U256::from_big_endian(val1); 485 | state.pc += n; // pc will also be incremented by one 486 | state.stack.push(val); 487 | } else if op >= DUP1 && op <= DUP16 { 488 | let n = usize::from(op - DUP1 + 1); 489 | let val = state.stack[n]; 490 | state.stack.push(val); 491 | } else if op >= SWAP1 && op <= SWAP16 { 492 | let n = usize::from(op - SWAP1 + 1); 493 | let tmp = state.stack[n]; 494 | state.stack[n] = state.stack[0]; 495 | state.stack[0] = tmp; 496 | } else { 497 | 498 | match op { 499 | STOP => { return Halt; }, 500 | 501 | ADD => state.stack.apply_binary_op(Add::add), 502 | 503 | MUL => state.stack.apply_binary_op(Mul::mul), 504 | 505 | SUB => state.stack.apply_binary_op(Sub::sub), 506 | 507 | DIV => state.stack.apply_binary_op(|s0, s1| 508 | if s1.is_zero() { 509 | U256::zero() 510 | } else { 511 | s0 / s1 // can overflow, which is what we want 512 | } 513 | ), 514 | 515 | SDIV => state.stack.apply_binary_op(|s0,s1| 516 | if s1.is_zero() { 517 | U256::zero() 518 | } else { 519 | let min_value = (U256::one() << 255) - U256::one(); 520 | let negative_one = !U256::zero(); 521 | 522 | if s0 == min_value && s1 == negative_one { 523 | min_value 524 | } else { 525 | let divisor = S256(S256(s0).abs() / S256(s1).abs()); 526 | 527 | if S256(s0).sign() != S256(s1).sign() { 528 | divisor.invert().to_u256() 529 | } else { 530 | divisor.to_u256() 531 | } 532 | } 533 | } 534 | ), 535 | 536 | MOD => state.stack.apply_binary_op(|s0, s1| 537 | if s1.is_zero() { 538 | U256::zero() 539 | } else { 540 | s0 % s1 541 | } 542 | ), 543 | 544 | SMOD => state.stack.apply_binary_op(|s0,s1| 545 | if s1.is_zero() { 546 | U256::zero() 547 | } else { 548 | let res = S256(s0).abs() % S256(s1).abs(); 549 | if S256(s0).sign() { 550 | let res = !res + U256::one(); 551 | } 552 | res 553 | } 554 | ), 555 | 556 | // Intermediate calculations not subject to 2^256 modulo 557 | ADDMOD => state.stack.apply_ternary_op(|s0, s1, s2| 558 | if s2.is_zero() { 559 | U256::zero() 560 | } else { 561 | 562 | (s0 + s1) % s2 563 | } 564 | ), 565 | 566 | // Again, intermediates not subject to 2^256 mod 567 | MULMOD => state.stack.apply_ternary_op(|s0, s1, s2| 568 | if s2.is_zero() { 569 | U256::zero() 570 | } else { 571 | (s0 * s1) % s2 572 | } 573 | ), 574 | 575 | //Overflowing pow returns (result,overflow_bool) 576 | EXP => state.stack.apply_binary_op(|s0, s1| {s0.overflowing_pow(s1).0}), 577 | 578 | SIGNEXTEND => state.stack.apply_binary_op(|s0, s1| 579 | if s0 < From::from(31) { 580 | let bit = (s0.low_u64() * 8 + 7) as usize; 581 | let mask = (U256::one() << bit) - U256::one(); 582 | if s1.bit(bit) { 583 | s1 | !mask 584 | } else { 585 | s1 & mask 586 | } 587 | } else { 588 | s0 589 | } 590 | ), 591 | 592 | 593 | LT => state.stack.apply_binary_op(|x, y| bool_to_u256(x < y)), 594 | 595 | GT => state.stack.apply_binary_op(|x, y| bool_to_u256(x > y)), 596 | 597 | SLT => state.stack.apply_binary_op(|x, y| 598 | { 599 | let res = match (S256(x).sign(),S256(y).sign()) { 600 | (false,false) => x < y, 601 | (false,true) => false, 602 | (true,false) => true, 603 | (true,true) => S256(x).abs() >= S256(y).abs(), 604 | }; 605 | bool_to_u256(res) 606 | } 607 | ), 608 | 609 | SGT => state.stack.apply_binary_op(|x, y| 610 | { 611 | let res = match (S256(x).sign(),S256(y).sign()) { 612 | (false,false) => x > y, 613 | (false,true) => true, 614 | (true,false) => false, 615 | (true,true) => S256(x).abs() <= S256(y).abs(), 616 | }; 617 | bool_to_u256(res) 618 | } 619 | ), 620 | 621 | EQ => state.stack.apply_binary_op(|x, y| bool_to_u256(x == y)), 622 | 623 | ISZERO => state.stack.apply_unary_op(|x| bool_to_u256(x.is_zero())), 624 | 625 | AND => state.stack.apply_binary_op(BitAnd::bitand), 626 | 627 | OR => state.stack.apply_binary_op(BitOr::bitor), 628 | 629 | XOR => state.stack.apply_binary_op(BitXor::bitxor), 630 | 631 | NOT => state.stack.apply_unary_op(Not::not), 632 | 633 | BYTE => { 634 | let stk = &mut state.stack; 635 | let ix = stk[0].as_u64() as usize; 636 | let source = stk[1]; 637 | stk.pop(2); 638 | stk.push(U256::from_big_endian(&[source.byte(ix)])); 639 | }, 640 | 641 | // SHA3 => { 642 | // let mut hasher = Keccak256::default(); 643 | // let stt = self.state.borrow_mut(); 644 | // let mut stk = stt.stack.borrow_mut(); 645 | // let start = stk[0]; 646 | // let end = stk[1]; 647 | // let message = self.get_memory(start, end); 648 | // hasher.input(message); 649 | // let out = hasher.result(); 650 | 651 | // stk.pop(2); 652 | // stk.push(out); 653 | // stt.active_words = memory_expansion(stt.active_words, start, end); 654 | // } 655 | 656 | ADDRESS => state.stack.push(addr_to_u256(&self.env.owner)), 657 | 658 | // BALANCE => { 659 | // let addr = 660 | // self.state 661 | // } 662 | 663 | ORIGIN => state.stack.push(addr_to_u256(&self.env.origin)), 664 | 665 | CALLER => state.stack.push(addr_to_u256(&self.env.caller)), 666 | 667 | CALLVALUE => state.stack.push(self.env.transaction_value), 668 | 669 | // CALLDATALOAD => { 670 | // let ix = &mut self.state.stack[0]; 671 | // let data = self.env.data; 672 | // // XXX default to 0 for index out of bounds 673 | // let mut slice = data[ix..ix+32]; 674 | // self.state.stack.pop(1); 675 | // self.state.stack.push(U256::from(slice)); 676 | // } 677 | 678 | CALLDATASIZE => 679 | state.stack.push(U256::from(self.env.data.len())), 680 | 681 | // CALLDATACOPY => {} 682 | // CODESIZE => {} 683 | // CODECOPY => {} 684 | // GASPRICE => {} 685 | // EXTCODESIZE => {} 686 | // EXTCODECOPY => {} 687 | 688 | BLOCKHASH => panic!("unimplemented: BLOCKHASH"), 689 | 690 | COINBASE => 691 | state.stack.push(addr_to_u256(&self.block.beneficiary)), 692 | 693 | TIMESTAMP => 694 | state.stack.push(self.block.timestamp), 695 | 696 | NUMBER => 697 | state.stack.push(self.block.number), 698 | 699 | DIFFICULTY => 700 | state.stack.push(self.block.difficulty), 701 | 702 | GASLIMIT => 703 | state.stack.push(self.block.gas_limit), 704 | 705 | POP => state.stack.pop(1), 706 | 707 | MLOAD => { 708 | let loc = state.stack[0].low_u32() as usize; 709 | state.stack[0] = state.m_load(loc); 710 | }, 711 | 712 | MSTORE => { 713 | let loc = state.stack[0].low_u32() as usize; 714 | let val = state.stack[1]; 715 | 716 | state.m_store(loc, val); 717 | 718 | state.stack.pop(2); 719 | }, 720 | 721 | MSTORE8 => { 722 | let loc = state.stack[0].low_u32() as usize; 723 | let val = state.stack[1].low_u32() as u8; 724 | 725 | state.m_store8(loc, val); 726 | 727 | state.stack.pop(2); 728 | }, 729 | 730 | JUMP => { 731 | let loc = state.stack[0]; 732 | state.stack.pop(1); 733 | state.pc = loc.low_u64() as usize; 734 | return Normal; 735 | }, 736 | 737 | JUMPI => { 738 | let loc = state.stack[0]; 739 | let b = state.stack[1]; 740 | state.stack.pop(2); 741 | 742 | if b != U256::zero() { 743 | state.pc = loc.low_u64() as usize; 744 | return Normal; 745 | }; 746 | }, 747 | 748 | PC => state.stack.push(U256::from(pc)), 749 | 750 | MSIZE => state.stack 751 | .push(U256::from(state.memory.len() * 32)), 752 | 753 | GAS => state.stack.push(state.gas_available), 754 | 755 | JUMPDEST => {} 756 | 757 | _ => panic!("unimplemented instruction: {}", op), 758 | } 759 | }; 760 | 761 | state.pc += 1; 762 | 763 | Normal 764 | } 765 | 766 | pub fn run(&mut self) { 767 | while self.state.pc < self.state.code.len() { 768 | self.step(); 769 | } 770 | } 771 | } 772 | 773 | fn init_vm(code: &Vec, gas: u32) -> VM { 774 | VM { 775 | result: None, 776 | state: FrameState { 777 | code: code.clone(), 778 | gas_available: U256::from(gas), 779 | pc: 0, 780 | memory: Vec::new(), 781 | active_words: U256::zero(), 782 | stack: Stack::new(), 783 | }, 784 | env: Env { 785 | owner: Address([0; 20]), 786 | origin: Address([0; 20]), 787 | gas_price: U256::zero(), 788 | data: Vec::new(), 789 | caller: Address([0; 20]), 790 | transaction_value: U256::zero(), 791 | code: Vec::new(), 792 | header: Header {}, 793 | depth: 0, 794 | }, 795 | block: Block { 796 | beneficiary: Address([0; 20]), 797 | difficulty: U256::one(), 798 | number: U256::one(), 799 | gas_limit: U256::one(), 800 | timestamp: U256::one(), 801 | } 802 | } 803 | } 804 | 805 | #[cfg(test)] 806 | mod tests { 807 | use *; 808 | 809 | #[test] 810 | fn it_works() { 811 | let mut vm = init_vm(&vec![PUSH1, 1, PUSH1, 2, ADD], 100); 812 | vm.run(); 813 | assert_eq!(vm.state.stack[0].as_u32(), 3); 814 | 815 | let mut vm = init_vm(&vec![PUSH1, 1, PUSH1, 2, MUL], 100); 816 | vm.run(); 817 | assert_eq!(vm.state.stack[0].as_u32(), 2); 818 | 819 | let mut vm = init_vm(&vec![PUSH1, 1, PUSH1, 2, SUB], 100); 820 | vm.run(); 821 | assert_eq!(vm.state.stack[0].as_u32(), 1); 822 | 823 | let mut vm = init_vm(&vec![PUSH1, 1, PUSH1, 2, DIV], 100); 824 | vm.run(); 825 | assert_eq!(vm.state.stack[0].as_u32(), 2); 826 | 827 | let mut vm = init_vm(&vec![PUSH1, 2, PUSH1, 1, GT], 100); 828 | vm.run(); 829 | assert_eq!(vm.state.stack[0].as_u32(), 0); 830 | 831 | let mut vm = init_vm(&vec![PUSH1, 2, PUSH1, 1, LT], 100); 832 | vm.run(); 833 | assert_eq!(vm.state.stack[0].as_u32(), 1); 834 | 835 | // store 123 at 200, then load it back 836 | // 7 words = 200 / 32 837 | let mut vm = init_vm(&vec![PUSH1, 123, PUSH1, 200, MSTORE, PUSH1, 200, MLOAD], 100); 838 | vm.run(); 839 | assert_eq!(vm.state.stack[0].as_u32(), 123); 840 | assert_eq!(vm.state.active_words.as_u32(), 7); 841 | 842 | let mut vm = init_vm(&vec![PUSH1, 123, PUSH1, 231, MSTORE8, PUSH1, 200, MLOAD], 100); 843 | vm.run(); 844 | assert_eq!(vm.state.stack[0].as_u32(), 123); 845 | assert_eq!(vm.state.active_words.as_u32(), 7); 846 | 847 | let mut vm = init_vm(&vec![PUSH1, 20, JUMP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PUSH1, 123], 100); 848 | vm.run(); 849 | assert_eq!(vm.state.stack[0].as_u32(), 123); 850 | 851 | // Div by zero 852 | let mut vm = init_vm(&vec![PUSH1, 0, PUSH1, 1, DIV], 100); 853 | vm.run(); 854 | assert_eq!(vm.state.stack[0].as_u32(), 0); 855 | } 856 | } 857 | --------------------------------------------------------------------------------