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.

354 lines
5.2 KiB

  1. package vm
  2. import (
  3. "fmt"
  4. "gopkg.in/fatih/set.v0"
  5. )
  6. type OpCode byte
  7. // Op codes
  8. const (
  9. // 0x0 range - arithmetic ops
  10. STOP OpCode = iota
  11. ADD
  12. MUL
  13. SUB
  14. DIV
  15. SDIV
  16. MOD
  17. SMOD
  18. ADDMOD
  19. MULMOD
  20. EXP
  21. SIGNEXTEND
  22. )
  23. const (
  24. LT OpCode = iota + 0x10
  25. GT
  26. SLT
  27. SGT
  28. EQ
  29. ISZERO
  30. AND
  31. OR
  32. XOR
  33. NOT
  34. BYTE
  35. SHA3 = 0x20
  36. )
  37. const (
  38. // 0x30 range - closure state
  39. ADDRESS OpCode = 0x30 + iota
  40. BALANCE
  41. ORIGIN
  42. CALLER
  43. CALLVALUE
  44. CALLDATALOAD
  45. CALLDATASIZE
  46. CALLDATACOPY
  47. CODESIZE
  48. CODECOPY
  49. GASPRICE
  50. EXTCODESIZE
  51. EXTCODECOPY
  52. )
  53. const (
  54. // 0x40 range - block operations
  55. BLOCKHASH OpCode = 0x40 + iota
  56. COINBASE
  57. TIMESTAMP
  58. BLOCKHEIGHT
  59. DIFFICULTY_DEPRECATED
  60. GASLIMIT
  61. )
  62. const (
  63. // 0x50 range - 'storage' and execution
  64. POP OpCode = 0x50 + iota
  65. MLOAD
  66. MSTORE
  67. MSTORE8
  68. SLOAD
  69. SSTORE
  70. JUMP
  71. JUMPI
  72. PC
  73. MSIZE
  74. GAS
  75. JUMPDEST
  76. )
  77. const (
  78. // 0x60 range
  79. PUSH1 OpCode = 0x60 + iota
  80. PUSH2
  81. PUSH3
  82. PUSH4
  83. PUSH5
  84. PUSH6
  85. PUSH7
  86. PUSH8
  87. PUSH9
  88. PUSH10
  89. PUSH11
  90. PUSH12
  91. PUSH13
  92. PUSH14
  93. PUSH15
  94. PUSH16
  95. PUSH17
  96. PUSH18
  97. PUSH19
  98. PUSH20
  99. PUSH21
  100. PUSH22
  101. PUSH23
  102. PUSH24
  103. PUSH25
  104. PUSH26
  105. PUSH27
  106. PUSH28
  107. PUSH29
  108. PUSH30
  109. PUSH31
  110. PUSH32
  111. DUP1
  112. DUP2
  113. DUP3
  114. DUP4
  115. DUP5
  116. DUP6
  117. DUP7
  118. DUP8
  119. DUP9
  120. DUP10
  121. DUP11
  122. DUP12
  123. DUP13
  124. DUP14
  125. DUP15
  126. DUP16
  127. SWAP1
  128. SWAP2
  129. SWAP3
  130. SWAP4
  131. SWAP5
  132. SWAP6
  133. SWAP7
  134. SWAP8
  135. SWAP9
  136. SWAP10
  137. SWAP11
  138. SWAP12
  139. SWAP13
  140. SWAP14
  141. SWAP15
  142. SWAP16
  143. )
  144. const (
  145. LOG0 OpCode = 0xa0 + iota
  146. LOG1
  147. LOG2
  148. LOG3
  149. LOG4
  150. )
  151. const (
  152. // 0xf0 range - closures
  153. CREATE OpCode = 0xf0 + iota
  154. CALL
  155. CALLCODE
  156. RETURN
  157. // 0x70 range - other
  158. SUICIDE = 0xff
  159. )
  160. // Since the opcodes aren't all in order we can't use a regular slice
  161. var opCodeToString = map[OpCode]string{
  162. // 0x0 range - arithmetic ops
  163. STOP: "STOP",
  164. ADD: "ADD",
  165. MUL: "MUL",
  166. SUB: "SUB",
  167. DIV: "DIV",
  168. SDIV: "SDIV",
  169. MOD: "MOD",
  170. SMOD: "SMOD",
  171. EXP: "EXP",
  172. NOT: "NOT",
  173. LT: "LT",
  174. GT: "GT",
  175. SLT: "SLT",
  176. SGT: "SGT",
  177. EQ: "EQ",
  178. ISZERO: "ISZERO",
  179. SIGNEXTEND: "SIGNEXTEND",
  180. // 0x10 range - bit ops
  181. AND: "AND",
  182. OR: "OR",
  183. XOR: "XOR",
  184. BYTE: "BYTE",
  185. ADDMOD: "ADDMOD",
  186. MULMOD: "MULMOD",
  187. // 0x20 range - crypto
  188. SHA3: "SHA3",
  189. // 0x30 range - closure state
  190. ADDRESS: "ADDRESS",
  191. BALANCE: "BALANCE",
  192. ORIGIN: "ORIGIN",
  193. CALLER: "CALLER",
  194. CALLVALUE: "CALLVALUE",
  195. CALLDATALOAD: "CALLDATALOAD",
  196. CALLDATASIZE: "CALLDATASIZE",
  197. CALLDATACOPY: "CALLDATACOPY",
  198. CODESIZE: "CODESIZE",
  199. CODECOPY: "CODECOPY",
  200. GASPRICE: "TXGASPRICE",
  201. // 0x40 range - block operations
  202. BLOCKHASH: "BLOCKHASH",
  203. COINBASE: "COINBASE",
  204. TIMESTAMP: "TIMESTAMP",
  205. BLOCKHEIGHT: "BLOCKHEIGHT",
  206. DIFFICULTY_DEPRECATED: "DIFFICULTY_DEPRECATED",
  207. GASLIMIT: "GASLIMIT",
  208. EXTCODESIZE: "EXTCODESIZE",
  209. EXTCODECOPY: "EXTCODECOPY",
  210. // 0x50 range - 'storage' and execution
  211. POP: "POP",
  212. //DUP: "DUP",
  213. //SWAP: "SWAP",
  214. MLOAD: "MLOAD",
  215. MSTORE: "MSTORE",
  216. MSTORE8: "MSTORE8",
  217. SLOAD: "SLOAD",
  218. SSTORE: "SSTORE",
  219. JUMP: "JUMP",
  220. JUMPI: "JUMPI",
  221. PC: "PC",
  222. MSIZE: "MSIZE",
  223. GAS: "GAS",
  224. JUMPDEST: "JUMPDEST",
  225. // 0x60 range - push
  226. PUSH1: "PUSH1",
  227. PUSH2: "PUSH2",
  228. PUSH3: "PUSH3",
  229. PUSH4: "PUSH4",
  230. PUSH5: "PUSH5",
  231. PUSH6: "PUSH6",
  232. PUSH7: "PUSH7",
  233. PUSH8: "PUSH8",
  234. PUSH9: "PUSH9",
  235. PUSH10: "PUSH10",
  236. PUSH11: "PUSH11",
  237. PUSH12: "PUSH12",
  238. PUSH13: "PUSH13",
  239. PUSH14: "PUSH14",
  240. PUSH15: "PUSH15",
  241. PUSH16: "PUSH16",
  242. PUSH17: "PUSH17",
  243. PUSH18: "PUSH18",
  244. PUSH19: "PUSH19",
  245. PUSH20: "PUSH20",
  246. PUSH21: "PUSH21",
  247. PUSH22: "PUSH22",
  248. PUSH23: "PUSH23",
  249. PUSH24: "PUSH24",
  250. PUSH25: "PUSH25",
  251. PUSH26: "PUSH26",
  252. PUSH27: "PUSH27",
  253. PUSH28: "PUSH28",
  254. PUSH29: "PUSH29",
  255. PUSH30: "PUSH30",
  256. PUSH31: "PUSH31",
  257. PUSH32: "PUSH32",
  258. DUP1: "DUP1",
  259. DUP2: "DUP2",
  260. DUP3: "DUP3",
  261. DUP4: "DUP4",
  262. DUP5: "DUP5",
  263. DUP6: "DUP6",
  264. DUP7: "DUP7",
  265. DUP8: "DUP8",
  266. DUP9: "DUP9",
  267. DUP10: "DUP10",
  268. DUP11: "DUP11",
  269. DUP12: "DUP12",
  270. DUP13: "DUP13",
  271. DUP14: "DUP14",
  272. DUP15: "DUP15",
  273. DUP16: "DUP16",
  274. SWAP1: "SWAP1",
  275. SWAP2: "SWAP2",
  276. SWAP3: "SWAP3",
  277. SWAP4: "SWAP4",
  278. SWAP5: "SWAP5",
  279. SWAP6: "SWAP6",
  280. SWAP7: "SWAP7",
  281. SWAP8: "SWAP8",
  282. SWAP9: "SWAP9",
  283. SWAP10: "SWAP10",
  284. SWAP11: "SWAP11",
  285. SWAP12: "SWAP12",
  286. SWAP13: "SWAP13",
  287. SWAP14: "SWAP14",
  288. SWAP15: "SWAP15",
  289. SWAP16: "SWAP16",
  290. LOG0: "LOG0",
  291. LOG1: "LOG1",
  292. LOG2: "LOG2",
  293. LOG3: "LOG3",
  294. LOG4: "LOG4",
  295. // 0xf0 range
  296. CREATE: "CREATE",
  297. CALL: "CALL",
  298. RETURN: "RETURN",
  299. CALLCODE: "CALLCODE",
  300. // 0x70 range - other
  301. SUICIDE: "SUICIDE",
  302. }
  303. func (o OpCode) String() string {
  304. str := opCodeToString[o]
  305. if len(str) == 0 {
  306. return fmt.Sprintf("Missing opcode 0x%x", int(o))
  307. }
  308. return str
  309. }
  310. //-----------------------------------------------------------------------------
  311. func AnalyzeJumpDests(code []byte) (dests *set.Set) {
  312. dests = set.New()
  313. for pc := uint64(0); pc < uint64(len(code)); pc++ {
  314. var op OpCode = OpCode(code[pc])
  315. switch op {
  316. case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
  317. a := uint64(op) - uint64(PUSH1) + 1
  318. pc += a
  319. case JUMPDEST:
  320. dests.Add(pc)
  321. }
  322. }
  323. return
  324. }