You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

490 lines
19 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. use super::*;
  2. use num_bigint::BigUint;
  3. use num_traits::identities::Zero;
  4. // Non-opcode gas prices
  5. const GDEFAULT: usize = 1;
  6. const GMEMORY: usize = 3;
  7. const GQUADRATICMEMDENOM: usize = 512; // 1 gas per 512 quadwords
  8. const GSTORAGEREFUND: usize = 15000;
  9. const GSTORAGEKILL: usize = 5000;
  10. const GSTORAGEMOD: usize = 5000;
  11. const GSTORAGEADD: usize = 20000;
  12. const NETSSTORENOOPGAS: u64 = 200;
  13. const NETSSTOREINITGAS: u64 = 20000;
  14. const NETSSTORECLEARREFUND: u64 = 15000;
  15. const NETSSTORERESETCLEARREFUND: u64 = 19800;
  16. const NETSSTORERESETREFUND: u64 = 4800;
  17. const NETSSTORECLEANGAS: u64 = 5000;
  18. const NETSSTOREDIRTYGAS: u64 = 200;
  19. const GEXPONENTBYTE: usize = 10; // cost of EXP exponent per byte
  20. const EXP_SUPPLEMENTAL_GAS: usize = 40;
  21. const GCOPY: usize = 3; // cost to copy one 32 byte word
  22. const GCONTRACTBYTE: usize = 200; // one byte of code in contract creation
  23. const GCALLVALUETRANSFER: usize = 9000; // non-zero-valued call
  24. const GLOGBYTE: usize = 8; // cost of a byte of logdata
  25. const GTXCOST: usize = 21000; // TX BASE GAS COST
  26. const GTXDATAZERO: usize = 4; // TX DATA ZERO BYTE GAS COST
  27. const GTXDATANONZERO: usize = 68; // TX DATA NON ZERO BYTE GAS COST
  28. const GSHA3WORD: usize = 6; // Cost of SHA3 per word
  29. const GSHA256BASE: usize = 60; // Base c of SHA256
  30. const GSHA256WORD: usize = 12; // Cost of SHA256 per word
  31. const GRIPEMD160BASE: usize = 600; // Base cost of RIPEMD160
  32. const GRIPEMD160WORD: usize = 120; // Cost of RIPEMD160 per word
  33. const GIDENTITYBASE: usize = 15; // Base cost of indentity
  34. const GIDENTITYWORD: usize = 3; // Cost of identity per word
  35. const GECRECOVER: usize = 3000; // Cost of ecrecover op
  36. const GSTIPEND: usize = 2300;
  37. const GCALLNEWACCOUNT: usize = 25000;
  38. const GSUICIDEREFUND: usize = 24000;
  39. pub struct Opcode {
  40. pub name: String,
  41. pub ins: u32,
  42. pub outs: u32,
  43. pub gas: u64,
  44. }
  45. pub fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
  46. Opcode {
  47. name: name.to_string(),
  48. ins,
  49. outs,
  50. gas,
  51. }
  52. }
  53. pub fn new_opcodes() -> HashMap<u8, Opcode> {
  54. let mut opcodes: HashMap<u8, Opcode> = HashMap::new();
  55. // arithmetic
  56. opcodes.insert(0x00, new_opcode("STOP", 0, 0, 0));
  57. opcodes.insert(0x01, new_opcode("ADD", 2, 1, 3));
  58. opcodes.insert(0x02, new_opcode("MUL", 2, 1, 5));
  59. opcodes.insert(0x03, new_opcode("SUB", 2, 1, 3));
  60. opcodes.insert(0x04, new_opcode("DIV", 2, 1, 5));
  61. opcodes.insert(0x05, new_opcode("SDIV", 2, 1, 5));
  62. opcodes.insert(0x06, new_opcode("MOD", 2, 1, 5));
  63. opcodes.insert(0x07, new_opcode("SMOD", 2, 1, 5));
  64. opcodes.insert(0x08, new_opcode("ADDMOD", 3, 1, 8));
  65. opcodes.insert(0x09, new_opcode("MULMOD", 3, 1, 8));
  66. opcodes.insert(0x0a, new_opcode("EXP", 2, 1, 10));
  67. opcodes.insert(0x0b, new_opcode("SIGNEXTEND", 2, 1, 5));
  68. // boolean
  69. opcodes.insert(0x10, new_opcode("LT", 2, 1, 3));
  70. opcodes.insert(0x11, new_opcode("GT", 2, 1, 3));
  71. opcodes.insert(0x12, new_opcode("SLT", 2, 1, 3));
  72. opcodes.insert(0x13, new_opcode("SGT", 2, 1, 3));
  73. opcodes.insert(0x14, new_opcode("EQ", 2, 1, 3));
  74. opcodes.insert(0x15, new_opcode("ISZERO", 1, 1, 3));
  75. opcodes.insert(0x16, new_opcode("AND", 2, 1, 3));
  76. opcodes.insert(0x17, new_opcode("OR", 2, 1, 3));
  77. opcodes.insert(0x18, new_opcode("XOR", 2, 1, 3));
  78. opcodes.insert(0x19, new_opcode("NOT", 1, 1, 3));
  79. opcodes.insert(0x1a, new_opcode("BYTE", 2, 1, 3));
  80. // crypto
  81. opcodes.insert(0x20, new_opcode("SHA3", 2, 1, 30));
  82. // contract context
  83. opcodes.insert(0x30, new_opcode("ADDRESS", 0, 1, 2));
  84. opcodes.insert(0x31, new_opcode("BALANCE", 1, 1, 20));
  85. opcodes.insert(0x32, new_opcode("ORIGIN", 0, 1, 2));
  86. opcodes.insert(0x33, new_opcode("CALLER", 0, 1, 2));
  87. opcodes.insert(0x34, new_opcode("CALLVALUE", 0, 1, 2));
  88. opcodes.insert(0x35, new_opcode("CALLDATALOAD", 1, 1, 3));
  89. opcodes.insert(0x36, new_opcode("CALLDATASIZE", 0, 1, 2));
  90. opcodes.insert(0x37, new_opcode("CALLDATACOPY", 3, 0, 3));
  91. opcodes.insert(0x38, new_opcode("CODESIZE", 0, 1, 2));
  92. opcodes.insert(0x39, new_opcode("CODECOPY", 3, 0, 3));
  93. opcodes.insert(0x3a, new_opcode("GASPRICE", 0, 1, 2));
  94. opcodes.insert(0x3b, new_opcode("EXTCODESIZE", 1, 1, 20));
  95. opcodes.insert(0x3c, new_opcode("EXTCODECOPY", 4, 0, 20));
  96. // blockchain context
  97. opcodes.insert(0x40, new_opcode("BLOCKHASH", 1, 1, 20));
  98. opcodes.insert(0x41, new_opcode("COINBASE", 0, 1, 2));
  99. opcodes.insert(0x42, new_opcode("TIMESTAMP", 0, 1, 2));
  100. opcodes.insert(0x43, new_opcode("NUMBER", 0, 1, 2));
  101. opcodes.insert(0x44, new_opcode("DIFFICULTY", 0, 1, 2));
  102. opcodes.insert(0x45, new_opcode("GASLIMIT", 0, 1, 2));
  103. // storage and execution
  104. opcodes.insert(0x50, new_opcode("POP", 1, 0, 2));
  105. opcodes.insert(0x51, new_opcode("MLOAD", 1, 1, 3));
  106. opcodes.insert(0x52, new_opcode("MSTORE", 2, 0, 3));
  107. opcodes.insert(0x53, new_opcode("MSTORE8", 2, 0, 3));
  108. opcodes.insert(0x54, new_opcode("SLOAD", 1, 1, 50));
  109. opcodes.insert(0x55, new_opcode("SSTORE", 2, 0, 0));
  110. opcodes.insert(0x56, new_opcode("JUMP", 1, 0, 8));
  111. opcodes.insert(0x57, new_opcode("JUMPI", 2, 0, 10));
  112. opcodes.insert(0x58, new_opcode("PC", 0, 1, 2));
  113. opcodes.insert(0x59, new_opcode("MSIZE", 0, 1, 2));
  114. opcodes.insert(0x5a, new_opcode("GAS", 0, 1, 2));
  115. opcodes.insert(0x5b, new_opcode("JUMPDEST", 0, 0, 1));
  116. // logging
  117. opcodes.insert(0xa0, new_opcode("LOG0", 2, 0, 375));
  118. opcodes.insert(0xa1, new_opcode("LOG1", 3, 0, 750));
  119. opcodes.insert(0xa2, new_opcode("LOG2", 4, 0, 1125));
  120. opcodes.insert(0xa3, new_opcode("LOG3", 5, 0, 1500));
  121. opcodes.insert(0xa4, new_opcode("LOG4", 6, 0, 1875));
  122. // closures
  123. opcodes.insert(0xf0, new_opcode("CREATE", 3, 1, 32000));
  124. opcodes.insert(0xf1, new_opcode("CALL", 7, 1, 40));
  125. opcodes.insert(0xf2, new_opcode("CALLCODE", 7, 1, 40));
  126. opcodes.insert(0xf3, new_opcode("RETURN", 2, 0, 0));
  127. opcodes.insert(0xf4, new_opcode("DELEGATECALL", 6, 0, 40));
  128. opcodes.insert(0xff, new_opcode("SUICIDE", 1, 0, 0));
  129. for i in 1..33 {
  130. let name = format!("PUSH{}", i);
  131. opcodes.insert(0x5f + i, new_opcode(&name, 0, 1, 3));
  132. }
  133. for i in 1..17 {
  134. let name = format!("DUP{}", i);
  135. opcodes.insert(0x7f + i, new_opcode(&name, i as u32, i as u32 + 1, 3));
  136. let name = format!("SWAP{}", i);
  137. opcodes.insert(0x8f + i, new_opcode(&name, i as u32 + 1, i as u32 + 1, 3));
  138. }
  139. opcodes
  140. }
  141. impl Stack {
  142. // arithmetic
  143. // TODO instead of [u8;32] converted to BigUint, use custom type uint256 that implements all
  144. // the arithmetic
  145. pub fn add(&mut self) -> Result<(), String> {
  146. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  147. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  148. self.push_arbitrary(&(b0 + b1).to_bytes_be());
  149. Ok(())
  150. }
  151. pub fn mul(&mut self) -> Result<(), String> {
  152. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  153. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  154. self.push_arbitrary(&(b0 * b1).to_bytes_be());
  155. Ok(())
  156. }
  157. pub fn sub(&mut self) -> Result<(), String> {
  158. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  159. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  160. if b0 >= b1 {
  161. self.push_arbitrary(&(b0 - b1).to_bytes_be());
  162. } else {
  163. // 2**256 TODO this will not be here hardcoded, there will be a custom type uint256
  164. let max =
  165. "115792089237316195423570985008687907853269984665640564039457584007913129639936"
  166. .parse::<BigUint>()
  167. .unwrap();
  168. self.push_arbitrary(&(max + b0 - b1).to_bytes_be());
  169. }
  170. Ok(())
  171. }
  172. pub fn div(&mut self) -> Result<(), String> {
  173. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  174. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  175. self.push_arbitrary(&(b0 / b1).to_bytes_be());
  176. Ok(())
  177. }
  178. pub fn sdiv(&mut self) -> Result<(), String> {
  179. Err("unimplemented".to_string())
  180. }
  181. pub fn modulus(&mut self) -> Result<(), String> {
  182. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  183. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  184. self.push_arbitrary(&(b0 % b1).to_bytes_be());
  185. Ok(())
  186. }
  187. pub fn smod(&mut self) -> Result<(), String> {
  188. Err("unimplemented".to_string())
  189. }
  190. pub fn add_mod(&mut self) -> Result<(), String> {
  191. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  192. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  193. let b2 = BigUint::from_bytes_be(&self.pop()?[..]);
  194. self.push_arbitrary(&(b0 + b1 % b2).to_bytes_be());
  195. Ok(())
  196. }
  197. pub fn mul_mod(&mut self) -> Result<(), String> {
  198. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  199. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  200. let b2 = BigUint::from_bytes_be(&self.pop()?[..]);
  201. self.push_arbitrary(&(b0 * b1 % b2).to_bytes_be());
  202. Ok(())
  203. }
  204. pub fn exp(&mut self) -> Result<(), String> {
  205. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  206. let e = BigUint::from_bytes_be(&self.pop()?[..]);
  207. let mut r = "1".parse::<BigUint>().unwrap();
  208. let zero = "0".parse::<BigUint>().unwrap();
  209. let mut rem = e.clone();
  210. let mut exp = b;
  211. // 2**256 TODO this will not be here hardcoded, there will be a custom type uint256
  212. let field =
  213. "115792089237316195423570985008687907853269984665640564039457584007913129639936"
  214. .parse::<BigUint>()
  215. .unwrap();
  216. while rem != zero {
  217. if rem.bit(0) {
  218. // is odd
  219. r = r * exp.clone() % field.clone();
  220. }
  221. exp = exp.clone() * exp.clone();
  222. rem >>= 1;
  223. }
  224. self.push_arbitrary(&r.to_bytes_be());
  225. let n_bytes = &e.to_bytes_be().len();
  226. let mut exp_fee = n_bytes * GEXPONENTBYTE;
  227. exp_fee += EXP_SUPPLEMENTAL_GAS * n_bytes;
  228. self.gas -= exp_fee as u64;
  229. Ok(())
  230. }
  231. // boolean
  232. pub fn lt(&mut self) -> Result<(), String> {
  233. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  234. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  235. self.push(u256::usize_to_u256((a < b) as usize));
  236. Ok(())
  237. }
  238. pub fn gt(&mut self) -> Result<(), String> {
  239. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  240. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  241. self.push(u256::usize_to_u256((a > b) as usize));
  242. Ok(())
  243. }
  244. pub fn eq(&mut self) -> Result<(), String> {
  245. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  246. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  247. self.push(u256::usize_to_u256((a == b) as usize));
  248. Ok(())
  249. }
  250. pub fn is_zero(&mut self) -> Result<(), String> {
  251. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  252. self.push(u256::usize_to_u256(a.is_zero() as usize));
  253. Ok(())
  254. }
  255. pub fn and(&mut self) -> Result<(), String> {
  256. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  257. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  258. self.push_arbitrary(&(a & b).to_bytes_be());
  259. Ok(())
  260. }
  261. pub fn or(&mut self) -> Result<(), String> {
  262. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  263. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  264. self.push_arbitrary(&(a | b).to_bytes_be());
  265. Ok(())
  266. }
  267. pub fn xor(&mut self) -> Result<(), String> {
  268. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  269. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  270. self.push_arbitrary(&(a ^ b).to_bytes_be());
  271. Ok(())
  272. }
  273. pub fn not(&mut self) -> Result<(), String> {
  274. // 2**256-1 TODO this will not be here hardcoded, there will be a custom type uint256
  275. let f = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
  276. .parse::<BigUint>()
  277. .unwrap();
  278. let a = BigUint::from_bytes_be(&self.pop()?[..]);
  279. self.push_arbitrary(&(f - a).to_bytes_be());
  280. Ok(())
  281. }
  282. // crypto
  283. // contract context
  284. pub fn calldata_load(&mut self, calldata: &[u8]) -> Result<(), String> {
  285. let mut start = self.calldata_i;
  286. if !self.stack.is_empty() {
  287. start = u256::u256_to_u64(self.peek()?) as usize;
  288. }
  289. let l = calldata.len();
  290. if start > l {
  291. start = l;
  292. }
  293. let mut end = start + self.calldata_size;
  294. if end > l {
  295. end = l;
  296. }
  297. self.put_arbitrary(&calldata[start..end]);
  298. self.calldata_i += self.calldata_size;
  299. Ok(())
  300. }
  301. pub fn calldata_size(&mut self, calldata: &[u8]) {
  302. self.calldata_size = calldata.len();
  303. self.push(u256::usize_to_u256(self.calldata_size));
  304. }
  305. fn spend_gas_data_copy(&mut self, length: usize) {
  306. let length32 = upper_multiple_of_32(length);
  307. self.gas -= ((GCOPY * length32) / 32) as u64;
  308. }
  309. pub fn code_copy(&mut self, code: &[u8]) -> Result<(), String> {
  310. let dest_offset = u256::u256_to_u64(self.pop()?) as usize;
  311. let offset = u256::u256_to_u64(self.pop()?) as usize;
  312. let length = u256::u256_to_u64(self.pop()?) as usize;
  313. self.extend_mem(dest_offset, length);
  314. self.spend_gas_data_copy(length);
  315. for i in 0..length {
  316. if offset + i < code.len() {
  317. self.mem[dest_offset + i] = code[offset + i];
  318. } else {
  319. self.mem[dest_offset + i] = 0;
  320. }
  321. }
  322. // self.mem[dest_offset..dest_offset+length] =
  323. Ok(())
  324. }
  325. // blockchain context
  326. // storage and execution
  327. pub fn extend_mem(&mut self, start: usize, size: usize) {
  328. if size <= self.mem.len() || start + size <= self.mem.len() {
  329. return;
  330. }
  331. let old_size = self.mem.len() / 32;
  332. let new_size = upper_multiple_of_32(start + size) / 32;
  333. let old_total_fee = old_size * GMEMORY + old_size.pow(2) / GQUADRATICMEMDENOM;
  334. let new_total_fee = new_size * GMEMORY + new_size.pow(2) / GQUADRATICMEMDENOM;
  335. let mem_fee = new_total_fee - old_total_fee;
  336. self.gas -= mem_fee as u64;
  337. let mut new_bytes: Vec<u8> = vec![0; (new_size - old_size) * 32];
  338. self.mem.append(&mut new_bytes);
  339. }
  340. pub fn mload(&mut self) -> Result<(), String> {
  341. let pos = u256::u256_to_u64(self.pop()?) as usize;
  342. self.extend_mem(pos as usize, 32);
  343. let mem32 = self.mem[pos..pos + 32].to_vec();
  344. self.push_arbitrary(&mem32);
  345. Ok(())
  346. }
  347. pub fn mstore(&mut self) -> Result<(), String> {
  348. let pos = u256::u256_to_u64(self.pop()?);
  349. let val = self.pop()?;
  350. self.extend_mem(pos as usize, 32);
  351. self.mem[pos as usize..].copy_from_slice(&val);
  352. Ok(())
  353. }
  354. pub fn sstore(&mut self) -> Result<(), String> {
  355. // https://eips.ethereum.org/EIPS/eip-3529
  356. // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1283.md
  357. // 1. If current value equals new value (this is a no-op), 200 gas is deducted.
  358. // 2. If current value does not equal new value
  359. // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
  360. // 2.1.1. If original value is 0, 20000 gas is deducted.
  361. // 2.1.2. Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter.
  362. // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
  363. // 2.2.1. If original value is not 0
  364. // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
  365. // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
  366. // 2.2.2. If original value equals new value (this storage slot is reset)
  367. // 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
  368. // 2.2.2.2. Otherwise, add 4800 gas to refund counter.
  369. let empty: Vec<u8> = Vec::new();
  370. let key = self.pop()?;
  371. let value = self.pop()?;
  372. let original = match self.storage_committed.get(&key) {
  373. Some(v) => v.clone(),
  374. None => empty.clone(),
  375. };
  376. let current = match self.storage.get(&key) {
  377. Some(v) => v.clone(),
  378. None => {
  379. self.gas -= 2100;
  380. empty.clone()
  381. }
  382. };
  383. if current == value {
  384. self.gas -= NETSSTORENOOPGAS;
  385. return Ok(());
  386. }
  387. if original == current {
  388. if original.is_empty() {
  389. self.gas -= NETSSTOREINITGAS;
  390. return Ok(());
  391. }
  392. if value.is_empty() {
  393. self.gas += NETSSTORECLEARREFUND;
  394. }
  395. self.gas -= NETSSTORECLEANGAS;
  396. return Ok(());
  397. }
  398. if !original.is_empty() {
  399. if current.is_empty() {
  400. self.gas -= NETSSTORECLEARREFUND;
  401. } else if value.is_empty() {
  402. self.gas += NETSSTORECLEARREFUND;
  403. }
  404. }
  405. if original == value {
  406. if original.is_empty() {
  407. self.gas += NETSSTORERESETCLEARREFUND;
  408. } else {
  409. self.gas += NETSSTORERESETREFUND;
  410. }
  411. }
  412. self.gas -= NETSSTOREDIRTYGAS;
  413. self.storage.insert(key, value.to_vec());
  414. Ok(())
  415. }
  416. pub fn jump(&mut self, code: &[u8]) -> Result<(), String> {
  417. // TODO that jump destination is valid
  418. let new_pc = u256::u256_to_u64(self.pop()?) as usize;
  419. if !valid_dest(code, new_pc) {
  420. return Err(format!("not valid dest: {:02x}", new_pc));
  421. }
  422. self.pc = new_pc;
  423. Ok(())
  424. }
  425. pub fn jump_i(&mut self, code: &[u8]) -> Result<(), String> {
  426. let new_pc = u256::u256_to_u64(self.pop()?) as usize;
  427. if !valid_dest(code, new_pc) {
  428. return Err(format!("not valid dest: {:02x}", new_pc));
  429. }
  430. if !self.stack.is_empty() {
  431. let cond = u256::u256_to_u64(self.pop()?) as usize;
  432. if cond != 0 {
  433. self.pc = new_pc;
  434. }
  435. }
  436. // let cont = self.pop();
  437. // if cont {} // TODO depends on having impl Err in pop()
  438. Ok(())
  439. }
  440. pub fn jump_dest(&mut self) -> Result<(), String> {
  441. // TODO
  442. Ok(())
  443. }
  444. }
  445. fn valid_dest(code: &[u8], pos: usize) -> bool {
  446. if code[pos] == 0x5b {
  447. return true;
  448. }
  449. false
  450. }
  451. fn upper_multiple_of_32(n: usize) -> usize {
  452. ((n - 1) | 31) + 1
  453. }