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.

362 lines
14 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
  1. use super::*;
  2. // Non-opcode gas prices
  3. const GDEFAULT: usize = 1;
  4. const GMEMORY: usize = 3;
  5. const GQUADRATICMEMDENOM: usize = 512; // 1 gas per 512 quadwords
  6. const GSTORAGEREFUND: usize = 15000;
  7. const GSTORAGEKILL: usize = 5000;
  8. const GSTORAGEMOD: usize = 5000;
  9. const GSTORAGEADD: usize = 20000;
  10. const GEXPONENTBYTE: usize = 10; // cost of EXP exponent per byte
  11. const EXP_SUPPLEMENTAL_GAS: usize = 40;
  12. const GCOPY: usize = 3; // cost to copy one 32 byte word
  13. const GCONTRACTBYTE: usize = 200; // one byte of code in contract creation
  14. const GCALLVALUETRANSFER: usize = 9000; // non-zero-valued call
  15. const GLOGBYTE: usize = 8; // cost of a byte of logdata
  16. const GTXCOST: usize = 21000; // TX BASE GAS COST
  17. const GTXDATAZERO: usize = 4; // TX DATA ZERO BYTE GAS COST
  18. const GTXDATANONZERO: usize = 68; // TX DATA NON ZERO BYTE GAS COST
  19. const GSHA3WORD: usize = 6; // Cost of SHA3 per word
  20. const GSHA256BASE: usize = 60; // Base c of SHA256
  21. const GSHA256WORD: usize = 12; // Cost of SHA256 per word
  22. const GRIPEMD160BASE: usize = 600; // Base cost of RIPEMD160
  23. const GRIPEMD160WORD: usize = 120; // Cost of RIPEMD160 per word
  24. const GIDENTITYBASE: usize = 15; // Base cost of indentity
  25. const GIDENTITYWORD: usize = 3; // Cost of identity per word
  26. const GECRECOVER: usize = 3000; // Cost of ecrecover op
  27. const GSTIPEND: usize = 2300;
  28. const GCALLNEWACCOUNT: usize = 25000;
  29. const GSUICIDEREFUND: usize = 24000;
  30. pub struct Opcode {
  31. pub name: String,
  32. pub ins: u32,
  33. pub outs: u32,
  34. pub gas: u64,
  35. // operation: fn(),
  36. }
  37. pub fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
  38. Opcode {
  39. name: name.to_string(),
  40. ins,
  41. outs,
  42. gas,
  43. }
  44. }
  45. pub fn new_opcodes() -> HashMap<u8, Opcode> {
  46. let mut opcodes: HashMap<u8, Opcode> = HashMap::new();
  47. // arithmetic
  48. opcodes.insert(0x00, new_opcode("STOP", 0, 0, 0));
  49. opcodes.insert(0x01, new_opcode("ADD", 2, 1, 3));
  50. opcodes.insert(0x02, new_opcode("MUL", 2, 1, 5));
  51. opcodes.insert(0x03, new_opcode("SUB", 2, 1, 3));
  52. opcodes.insert(0x04, new_opcode("DIV", 2, 1, 5));
  53. opcodes.insert(0x05, new_opcode("SDIV", 2, 1, 5));
  54. opcodes.insert(0x06, new_opcode("MOD", 2, 1, 5));
  55. opcodes.insert(0x07, new_opcode("SMOD", 2, 1, 5));
  56. opcodes.insert(0x08, new_opcode("ADDMOD", 3, 1, 8));
  57. opcodes.insert(0x09, new_opcode("MULMOD", 3, 1, 8));
  58. opcodes.insert(0x0a, new_opcode("EXP", 2, 1, 10));
  59. opcodes.insert(0x0b, new_opcode("SIGNEXTEND", 2, 1, 5));
  60. // boolean
  61. opcodes.insert(0x10, new_opcode("LT", 2, 1, 3));
  62. opcodes.insert(0x11, new_opcode("GT", 2, 1, 3));
  63. opcodes.insert(0x12, new_opcode("SLT", 2, 1, 3));
  64. opcodes.insert(0x13, new_opcode("SGT", 2, 1, 3));
  65. opcodes.insert(0x14, new_opcode("EQ", 2, 1, 3));
  66. opcodes.insert(0x15, new_opcode("ISZERO", 1, 1, 3));
  67. opcodes.insert(0x16, new_opcode("AND", 2, 1, 3));
  68. opcodes.insert(0x17, new_opcode("OR", 2, 1, 3));
  69. opcodes.insert(0x18, new_opcode("XOR", 2, 1, 3));
  70. opcodes.insert(0x19, new_opcode("NOT", 1, 1, 3));
  71. opcodes.insert(0x1a, new_opcode("BYTE", 2, 1, 3));
  72. // crypto
  73. opcodes.insert(0x20, new_opcode("SHA3", 2, 1, 30));
  74. // contract context
  75. opcodes.insert(0x30, new_opcode("ADDRESS", 0, 1, 2));
  76. opcodes.insert(0x31, new_opcode("BALANCE", 1, 1, 20));
  77. opcodes.insert(0x32, new_opcode("ORIGIN", 0, 1, 2));
  78. opcodes.insert(0x33, new_opcode("CALLER", 0, 1, 2));
  79. opcodes.insert(0x34, new_opcode("CALLVALUE", 0, 1, 2));
  80. opcodes.insert(0x35, new_opcode("CALLDATALOAD", 1, 1, 3));
  81. opcodes.insert(0x36, new_opcode("CALLDATASIZE", 0, 1, 2));
  82. opcodes.insert(0x37, new_opcode("CALLDATACOPY", 3, 0, 3));
  83. opcodes.insert(0x38, new_opcode("CODESIZE", 0, 1, 2));
  84. opcodes.insert(0x39, new_opcode("CODECOPY", 3, 0, 3));
  85. opcodes.insert(0x3a, new_opcode("GASPRICE", 0, 1, 2));
  86. opcodes.insert(0x3b, new_opcode("EXTCODESIZE", 1, 1, 20));
  87. opcodes.insert(0x3c, new_opcode("EXTCODECOPY", 4, 0, 20));
  88. // blockchain context
  89. opcodes.insert(0x40, new_opcode("BLOCKHASH", 1, 1, 20));
  90. opcodes.insert(0x41, new_opcode("COINBASE", 0, 1, 2));
  91. opcodes.insert(0x42, new_opcode("TIMESTAMP", 0, 1, 2));
  92. opcodes.insert(0x43, new_opcode("NUMBER", 0, 1, 2));
  93. opcodes.insert(0x44, new_opcode("DIFFICULTY", 0, 1, 2));
  94. opcodes.insert(0x45, new_opcode("GASLIMIT", 0, 1, 2));
  95. // storage and execution
  96. opcodes.insert(0x50, new_opcode("POP", 1, 0, 2));
  97. opcodes.insert(0x51, new_opcode("MLOAD", 1, 1, 3));
  98. opcodes.insert(0x52, new_opcode("MSTORE", 2, 0, 3));
  99. opcodes.insert(0x53, new_opcode("MSTORE8", 2, 0, 3));
  100. opcodes.insert(0x54, new_opcode("SLOAD", 1, 1, 50));
  101. opcodes.insert(0x55, new_opcode("SSTORE", 2, 0, 0));
  102. opcodes.insert(0x56, new_opcode("JUMP", 1, 0, 8));
  103. opcodes.insert(0x57, new_opcode("JUMPI", 2, 0, 10));
  104. opcodes.insert(0x58, new_opcode("PC", 0, 1, 2));
  105. opcodes.insert(0x59, new_opcode("MSIZE", 0, 1, 2));
  106. opcodes.insert(0x5a, new_opcode("GAS", 0, 1, 2));
  107. opcodes.insert(0x5b, new_opcode("JUMPDEST", 0, 0, 1));
  108. // logging
  109. opcodes.insert(0xa0, new_opcode("LOG0", 2, 0, 375));
  110. opcodes.insert(0xa1, new_opcode("LOG1", 3, 0, 750));
  111. opcodes.insert(0xa2, new_opcode("LOG2", 4, 0, 1125));
  112. opcodes.insert(0xa3, new_opcode("LOG3", 5, 0, 1500));
  113. opcodes.insert(0xa4, new_opcode("LOG4", 6, 0, 1875));
  114. // closures
  115. opcodes.insert(0xf0, new_opcode("CREATE", 3, 1, 32000));
  116. opcodes.insert(0xf1, new_opcode("CALL", 7, 1, 40));
  117. opcodes.insert(0xf2, new_opcode("CALLCODE", 7, 1, 40));
  118. opcodes.insert(0xf3, new_opcode("RETURN", 2, 0, 0));
  119. opcodes.insert(0xf4, new_opcode("DELEGATECALL", 6, 0, 40));
  120. opcodes.insert(0xff, new_opcode("SUICIDE", 1, 0, 0));
  121. for i in 1..33 {
  122. let name = format!("PUSH{}", i);
  123. opcodes.insert(0x5f + i, new_opcode(&name, 0, 1, 3));
  124. }
  125. for i in 1..17 {
  126. let name = format!("DUP{}", i);
  127. opcodes.insert(0x7f + i, new_opcode(&name, i as u32, i as u32 + 1, 3));
  128. let name = format!("SWAP{}", i);
  129. opcodes.insert(0x8f + i, new_opcode(&name, i as u32 + 1, i as u32 + 1, 3));
  130. }
  131. opcodes
  132. }
  133. impl Stack {
  134. // arithmetic
  135. // TODO instead of [u8;32] converted to BigUint, use custom type uint256 that implements all
  136. // the arithmetic
  137. pub fn add(&mut self) -> Result<(), String> {
  138. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  139. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  140. self.push_arbitrary(&(b0 + b1).to_bytes_be());
  141. Ok(())
  142. }
  143. pub fn mul(&mut self) -> Result<(), String> {
  144. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  145. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  146. self.push_arbitrary(&(b0 * b1).to_bytes_be());
  147. Ok(())
  148. }
  149. pub fn sub(&mut self) -> Result<(), String> {
  150. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  151. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  152. if b0 >= b1 {
  153. self.push_arbitrary(&(b0 - b1).to_bytes_be());
  154. } else {
  155. // 2**256 TODO this will not be here hardcoded, there will be a custom type uint256
  156. let max =
  157. "115792089237316195423570985008687907853269984665640564039457584007913129639936"
  158. .parse::<BigUint>()
  159. .unwrap();
  160. self.push_arbitrary(&(max + b0 - b1).to_bytes_be());
  161. }
  162. Ok(())
  163. }
  164. pub fn div(&mut self) -> Result<(), String> {
  165. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  166. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  167. self.push_arbitrary(&(b0 / b1).to_bytes_be());
  168. Ok(())
  169. }
  170. pub fn sdiv(&mut self) -> Result<(), String> {
  171. Err(format!("unimplemented"))
  172. }
  173. pub fn modulus(&mut self) -> Result<(), String> {
  174. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  175. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  176. self.push_arbitrary(&(b0 % b1).to_bytes_be());
  177. Ok(())
  178. }
  179. pub fn smod(&mut self) -> Result<(), String> {
  180. Err(format!("unimplemented"))
  181. }
  182. pub fn add_mod(&mut self) -> Result<(), String> {
  183. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  184. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  185. let b2 = BigUint::from_bytes_be(&self.pop()?[..]);
  186. self.push_arbitrary(&(b0 + b1 % b2).to_bytes_be());
  187. Ok(())
  188. }
  189. pub fn mul_mod(&mut self) -> Result<(), String> {
  190. let b0 = BigUint::from_bytes_be(&self.pop()?[..]);
  191. let b1 = BigUint::from_bytes_be(&self.pop()?[..]);
  192. let b2 = BigUint::from_bytes_be(&self.pop()?[..]);
  193. self.push_arbitrary(&(b0 * b1 % b2).to_bytes_be());
  194. Ok(())
  195. }
  196. pub fn exp(&mut self) -> Result<(), String> {
  197. let b = BigUint::from_bytes_be(&self.pop()?[..]);
  198. let e = BigUint::from_bytes_be(&self.pop()?[..]);
  199. let mut r = "1".parse::<BigUint>().unwrap();
  200. let zero = "0".parse::<BigUint>().unwrap();
  201. let mut rem = e.clone();
  202. let mut exp = b;
  203. // 2**256 TODO this will not be here hardcoded, there will be a custom type uint256
  204. let field =
  205. "115792089237316195423570985008687907853269984665640564039457584007913129639936"
  206. .parse::<BigUint>()
  207. .unwrap();
  208. while rem != zero {
  209. if rem.bit(0) {
  210. // is odd
  211. r = r * exp.clone() % field.clone();
  212. }
  213. exp = exp.clone() * exp.clone();
  214. rem >>= 1;
  215. }
  216. self.push_arbitrary(&r.to_bytes_be());
  217. let n_bytes = &e.to_bytes_be().len();
  218. let mut exp_fee = n_bytes * GEXPONENTBYTE;
  219. exp_fee += EXP_SUPPLEMENTAL_GAS * n_bytes;
  220. self.gas -= exp_fee as u64;
  221. Ok(())
  222. }
  223. // boolean
  224. // crypto
  225. // contract context
  226. pub fn calldata_load(&mut self, calldata: &[u8]) {
  227. self.put_arbitrary(&calldata[self.calldata_i..self.calldata_i + self.calldata_size]);
  228. self.calldata_i += self.calldata_size;
  229. }
  230. pub fn calldata_size(&mut self, calldata: &[u8]) {
  231. self.calldata_size = calldata.len();
  232. self.push(u256::usize_to_u256(self.calldata_size));
  233. }
  234. fn spend_gas_data_copy(&mut self, length: usize) {
  235. let length32 = upper_multiple_of_32(length);
  236. self.gas -= ((GCOPY * length32) / 32) as u64;
  237. }
  238. pub fn code_copy(&mut self, code: &[u8]) -> Result<(), String> {
  239. let dest_offset = u256::u256_to_u64(self.pop()?) as usize;
  240. let offset = u256::u256_to_u64(self.pop()?) as usize;
  241. let length = u256::u256_to_u64(self.pop()?) as usize;
  242. self.extend_mem(dest_offset, length);
  243. self.spend_gas_data_copy(length);
  244. for i in 0..length {
  245. if offset + i < code.len() {
  246. self.mem[dest_offset + i] = code[offset + i];
  247. } else {
  248. self.mem[dest_offset + i] = 0;
  249. }
  250. }
  251. // self.mem[dest_offset..dest_offset+length] =
  252. Ok(())
  253. }
  254. // blockchain context
  255. // storage and execution
  256. pub fn extend_mem(&mut self, start: usize, size: usize) {
  257. if size <= self.mem.len() || start + size <= self.mem.len() {
  258. return;
  259. }
  260. let old_size = self.mem.len() / 32;
  261. let new_size = upper_multiple_of_32(start + size) / 32;
  262. let old_total_fee = old_size * GMEMORY + old_size.pow(2) / GQUADRATICMEMDENOM;
  263. let new_total_fee = new_size * GMEMORY + new_size.pow(2) / GQUADRATICMEMDENOM;
  264. let mem_fee = new_total_fee - old_total_fee;
  265. self.gas -= mem_fee as u64;
  266. let mut new_bytes: Vec<u8> = vec![0; (new_size - old_size) * 32];
  267. self.mem.append(&mut new_bytes);
  268. }
  269. pub fn mload(&mut self) -> Result<(), String> {
  270. let pos = u256::u256_to_u64(self.pop()?) as usize;
  271. self.extend_mem(pos as usize, 32);
  272. let mem32 = self.mem[pos..pos + 32].to_vec();
  273. self.push_arbitrary(&mem32);
  274. Ok(())
  275. }
  276. pub fn mstore(&mut self) -> Result<(), String> {
  277. let pos = u256::u256_to_u64(self.pop()?);
  278. let val = self.pop()?;
  279. self.extend_mem(pos as usize, 32);
  280. self.mem[pos as usize..].copy_from_slice(&val);
  281. Ok(())
  282. }
  283. pub fn sstore(&mut self) -> Result<(), String> {
  284. let key = self.pop()?;
  285. let value = self.pop()?;
  286. if self.storage.contains_key(&key) {
  287. let old_value = self.storage.get(&key).unwrap();
  288. if &value.to_vec() == old_value {
  289. // if the new value is the same as the old one, do not set
  290. return Ok(());
  291. }
  292. // if value (from self.pop()) does not exist in the stack, is a STORAGEKILL TODO
  293. println!("mingas {:?}", GSTORAGEMOD);
  294. self.gas -= GSTORAGEMOD as u64;
  295. } else {
  296. // if value does not exist, substract gas for the addition
  297. println!("mingas {:?}", GSTORAGEADD);
  298. self.gas -= GSTORAGEADD as u64;
  299. }
  300. println!(
  301. "insert {:?} - {:?}",
  302. vec_u8_to_hex(key.to_vec()),
  303. vec_u8_to_hex(value.to_vec())
  304. );
  305. self.storage.insert(key, value.to_vec());
  306. Ok(())
  307. }
  308. pub fn jump(&mut self) -> Result<(), String> {
  309. // TODO that jump destination is valid
  310. self.pc = u256::u256_to_u64(self.pop()?) as usize;
  311. Ok(())
  312. }
  313. pub fn jump_i(&mut self) -> Result<(), String> {
  314. let new_pc = u256::u256_to_u64(self.pop()?) as usize;
  315. if !self.stack.is_empty() {
  316. let cond = u256::u256_to_u64(self.pop()?) as usize;
  317. if cond != 0 {
  318. self.pc = new_pc;
  319. }
  320. }
  321. // let cont = self.pop();
  322. // if cont {} // TODO depends on having impl Err in pop()
  323. Ok(())
  324. }
  325. pub fn jump_dest(&mut self) -> Result<(), String> {
  326. // TODO
  327. Ok(())
  328. }
  329. }
  330. fn upper_multiple_of_32(n: usize) -> usize {
  331. ((n - 1) | 31) + 1
  332. }