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.

217 lines
7.5 KiB

  1. #![allow(dead_code)]
  2. // use num::pow::pow;
  3. use num_bigint::BigUint;
  4. use std::collections::HashMap;
  5. // Non-opcode gas prices
  6. const GDEFAULT: usize = 1;
  7. const GMEMORY: usize = 3;
  8. const GQUADRATICMEMDENOM: usize = 512; // 1 gas per 512 quadwords
  9. const GSTORAGEREFUND: usize = 15000;
  10. const GSTORAGEKILL: usize = 5000;
  11. const GSTORAGEMOD: usize = 5000;
  12. const GSTORAGEADD: usize = 20000;
  13. const GEXPONENTBYTE: usize = 10; // cost of EXP exponent per byte
  14. const GCOPY: usize = 3; // cost to copy one 32 byte word
  15. const GCONTRACTBYTE: usize = 200; // one byte of code in contract creation
  16. const GCALLVALUETRANSFER: usize = 9000; // non-zero-valued call
  17. const GLOGBYTE: usize = 8; // cost of a byte of logdata
  18. const GTXCOST: usize = 21000; // TX BASE GAS COST
  19. const GTXDATAZERO: usize = 4; // TX DATA ZERO BYTE GAS COST
  20. const GTXDATANONZERO: usize = 68; // TX DATA NON ZERO BYTE GAS COST
  21. const GSHA3WORD: usize = 6; // Cost of SHA3 per word
  22. const GSHA256BASE: usize = 60; // Base c of SHA256
  23. const GSHA256WORD: usize = 12; // Cost of SHA256 per word
  24. const GRIPEMD160BASE: usize = 600; // Base cost of RIPEMD160
  25. const GRIPEMD160WORD: usize = 120; // Cost of RIPEMD160 per word
  26. const GIDENTITYBASE: usize = 15; // Base cost of indentity
  27. const GIDENTITYWORD: usize = 3; // Cost of identity per word
  28. const GECRECOVER: usize = 3000; // Cost of ecrecover op
  29. const GSTIPEND: usize = 2300;
  30. const GCALLNEWACCOUNT: usize = 25000;
  31. const GSUICIDEREFUND: usize = 24000;
  32. pub struct Stack {
  33. pc: usize,
  34. calldata_i: usize,
  35. stack: Vec<[u8; 32]>,
  36. mem: Vec<u8>,
  37. gas: u64,
  38. opcodes: HashMap<u8, Opcode>,
  39. }
  40. impl Stack {
  41. pub fn new() -> Stack {
  42. let mut s = Stack {
  43. pc: 0,
  44. calldata_i: 0,
  45. stack: Vec::new(),
  46. mem: Vec::new(),
  47. gas: 10000000000,
  48. opcodes: HashMap::new(),
  49. };
  50. s.opcodes = new_opcodes();
  51. s
  52. }
  53. fn push(&mut self, b: [u8; 32]) {
  54. self.stack.push(b);
  55. }
  56. fn pop(&mut self) -> [u8; 32] {
  57. match self.stack.pop() {
  58. Some(x) => return x,
  59. None => panic!("err"),
  60. }
  61. }
  62. }
  63. fn u256_to_u64(a: [u8; 32]) -> u64 {
  64. let mut b8: [u8; 8] = [0; 8];
  65. b8.copy_from_slice(&a[32 - 8..32]);
  66. let pos = u64::from_be_bytes(b8);
  67. pos
  68. }
  69. fn str_to_u256(s: &str) -> [u8; 32] {
  70. let bi = s.parse::<BigUint>().unwrap().to_bytes_be();
  71. let mut r: [u8; 32] = [0; 32];
  72. r[32 - bi.len()..].copy_from_slice(&bi[..]);
  73. r
  74. }
  75. struct Opcode {
  76. name: String,
  77. ins: u32,
  78. outs: u32,
  79. gas: u64,
  80. }
  81. fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
  82. Opcode {
  83. name: name.to_string(),
  84. ins,
  85. outs,
  86. gas,
  87. }
  88. }
  89. fn new_opcodes() -> HashMap<u8, Opcode> {
  90. let mut opcodes: HashMap<u8, Opcode> = HashMap::new();
  91. // arithmetic
  92. opcodes.insert(0x00, new_opcode("STOP", 0, 0, 0));
  93. opcodes.insert(0x01, new_opcode("ADD", 2, 1, 3));
  94. opcodes.insert(0x02, new_opcode("MUL", 2, 1, 5));
  95. opcodes.insert(0x03, new_opcode("SUB", 2, 1, 3));
  96. opcodes.insert(0x04, new_opcode("DIV", 2, 1, 5));
  97. opcodes.insert(0x05, new_opcode("SDIV", 2, 1, 5));
  98. opcodes.insert(0x06, new_opcode("MOD", 2, 1, 5));
  99. opcodes.insert(0x07, new_opcode("SMOD", 2, 1, 5));
  100. opcodes.insert(0x08, new_opcode("ADDMOD", 3, 1, 8));
  101. opcodes.insert(0x09, new_opcode("MULMOD", 3, 1, 8));
  102. opcodes.insert(0x0a, new_opcode("EXP", 2, 1, 10));
  103. opcodes.insert(0x0b, new_opcode("SIGNEXTEND", 2, 1, 5));
  104. // boolean
  105. opcodes.insert(0x10, new_opcode("LT", 2, 1, 3));
  106. opcodes.insert(0x11, new_opcode("GT", 2, 1, 3));
  107. opcodes.insert(0x12, new_opcode("SLT", 2, 1, 3));
  108. opcodes.insert(0x13, new_opcode("SGT", 2, 1, 3));
  109. opcodes.insert(0x14, new_opcode("EQ", 2, 1, 3));
  110. opcodes.insert(0x15, new_opcode("ISZERO", 1, 1, 3));
  111. opcodes.insert(0x16, new_opcode("AND", 2, 1, 3));
  112. opcodes.insert(0x17, new_opcode("OR", 2, 1, 3));
  113. opcodes.insert(0x18, new_opcode("XOR", 2, 1, 3));
  114. opcodes.insert(0x19, new_opcode("NOT", 1, 1, 3));
  115. opcodes.insert(0x1a, new_opcode("BYTE", 2, 1, 3));
  116. // crypto
  117. opcodes.insert(0x20, new_opcode("SHA3", 2, 1, 30));
  118. // contract context
  119. opcodes.insert(0x30, new_opcode("ADDRESS", 0, 1, 2));
  120. opcodes.insert(0x31, new_opcode("BALANCE", 1, 1, 20));
  121. opcodes.insert(0x32, new_opcode("ORIGIN", 0, 1, 2));
  122. opcodes.insert(0x33, new_opcode("CALLER", 0, 1, 2));
  123. opcodes.insert(0x34, new_opcode("CALLVALUE", 0, 1, 2));
  124. opcodes.insert(0x35, new_opcode("CALLDATALOAD", 1, 1, 3));
  125. opcodes.insert(0x36, new_opcode("CALLDATASIZE", 0, 1, 2));
  126. opcodes.insert(0x37, new_opcode("CALLDATACOPY", 3, 0, 3));
  127. opcodes.insert(0x38, new_opcode("CODESIZE", 0, 1, 2));
  128. opcodes.insert(0x39, new_opcode("CODECOPY", 3, 0, 3));
  129. opcodes.insert(0x3a, new_opcode("GASPRICE", 0, 1, 2));
  130. opcodes.insert(0x3b, new_opcode("EXTCODESIZE", 1, 1, 20));
  131. opcodes.insert(0x3c, new_opcode("EXTCODECOPY", 4, 0, 20));
  132. // blockchain context
  133. opcodes.insert(0x40, new_opcode("BLOCKHASH", 1, 1, 20));
  134. opcodes.insert(0x41, new_opcode("COINBASE", 0, 1, 2));
  135. opcodes.insert(0x42, new_opcode("TIMESTAMP", 0, 1, 2));
  136. opcodes.insert(0x43, new_opcode("NUMBER", 0, 1, 2));
  137. opcodes.insert(0x44, new_opcode("DIFFICULTY", 0, 1, 2));
  138. opcodes.insert(0x45, new_opcode("GASLIMIT", 0, 1, 2));
  139. // storage and execution
  140. opcodes.insert(0x50, new_opcode("POP", 1, 0, 2));
  141. opcodes.insert(0x51, new_opcode("MLOAD", 1, 1, 3));
  142. opcodes.insert(0x52, new_opcode("MSTORE", 2, 0, 3));
  143. opcodes.insert(0x53, new_opcode("MSTORE8", 2, 0, 3));
  144. opcodes.insert(0x54, new_opcode("SLOAD", 1, 1, 50));
  145. opcodes.insert(0x55, new_opcode("SSTORE", 2, 0, 0));
  146. opcodes.insert(0x56, new_opcode("JUMP", 1, 0, 8));
  147. opcodes.insert(0x57, new_opcode("JUMPI", 2, 0, 10));
  148. opcodes.insert(0x58, new_opcode("PC", 0, 1, 2));
  149. opcodes.insert(0x59, new_opcode("MSIZE", 0, 1, 2));
  150. opcodes.insert(0x5a, new_opcode("GAS", 0, 1, 2));
  151. opcodes.insert(0x5b, new_opcode("JUMPDEST", 0, 0, 1));
  152. // logging
  153. opcodes.insert(0xa0, new_opcode("LOG0", 2, 0, 375));
  154. opcodes.insert(0xa1, new_opcode("LOG1", 3, 0, 750));
  155. opcodes.insert(0xa2, new_opcode("LOG2", 4, 0, 1125));
  156. opcodes.insert(0xa3, new_opcode("LOG3", 5, 0, 1500));
  157. opcodes.insert(0xa4, new_opcode("LOG4", 6, 0, 1875));
  158. // closures
  159. opcodes.insert(0xf0, new_opcode("CREATE", 3, 1, 32000));
  160. opcodes.insert(0xf1, new_opcode("CALL", 7, 1, 40));
  161. opcodes.insert(0xf2, new_opcode("CALLCODE", 7, 1, 40));
  162. opcodes.insert(0xf3, new_opcode("RETURN", 2, 0, 0));
  163. opcodes.insert(0xf4, new_opcode("DELEGATECALL", 6, 0, 40));
  164. opcodes.insert(0xff, new_opcode("SUICIDE", 1, 0, 0));
  165. for i in 1..33 {
  166. let name = format!("PUSH{}", i);
  167. opcodes.insert(0x5f + i, new_opcode(&name, 0, 1, 3));
  168. }
  169. for i in 1..17 {
  170. let name = format!("DUP{}", i);
  171. opcodes.insert(0x7f + i, new_opcode(&name, i as u32, i as u32 + 1, 3));
  172. let name = format!("SWAP{}", i);
  173. opcodes.insert(0x8f + i, new_opcode(&name, i as u32 + 1, i as u32 + 1, 3));
  174. }
  175. opcodes
  176. }
  177. #[cfg(test)]
  178. mod tests {
  179. use super::*;
  180. #[test]
  181. fn stack_simple_push_pop() {
  182. let mut s = Stack::new();
  183. s.push(str_to_u256("1"));
  184. s.push(str_to_u256("2"));
  185. s.push(str_to_u256("3"));
  186. assert_eq!(s.pop(), str_to_u256("3"));
  187. assert_eq!(s.pop(), str_to_u256("2"));
  188. assert_eq!(s.pop(), str_to_u256("1"));
  189. // assert_eq!(s.pop(), str_to_u256("1"));
  190. // assert_eq!(s.pop(), error); // TODO expect error as stack is empty
  191. }
  192. }