instructions.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package vm
  17. import (
  18. "fmt"
  19. "math/big"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/crypto"
  22. "github.com/ethereum/go-ethereum/params"
  23. )
  24. type programInstruction interface {
  25. // executes the program instruction and allows the instruction to modify the state of the program
  26. do(program *Program, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
  27. // returns whether the program instruction halts the execution of the JIT
  28. halts() bool
  29. // Returns the current op code (debugging purposes)
  30. Op() OpCode
  31. }
  32. type instrFn func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack)
  33. type instruction struct {
  34. op OpCode
  35. pc uint64
  36. fn instrFn
  37. data *big.Int
  38. gas *big.Int
  39. spop int
  40. spush int
  41. returns bool
  42. }
  43. func jump(mapping map[uint64]uint64, destinations map[uint64]struct{}, contract *Contract, to *big.Int) (uint64, error) {
  44. if !validDest(destinations, to) {
  45. nop := contract.GetOp(to.Uint64())
  46. return 0, fmt.Errorf("invalid jump destination (%v) %v", nop, to)
  47. }
  48. return mapping[to.Uint64()], nil
  49. }
  50. func (instr instruction) do(program *Program, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
  51. // calculate the new memory size and gas price for the current executing opcode
  52. newMemSize, cost, err := jitCalculateGasAndSize(env, contract, instr, env.Db(), memory, stack)
  53. if err != nil {
  54. return nil, err
  55. }
  56. // Use the calculated gas. When insufficient gas is present, use all gas and return an
  57. // Out Of Gas error
  58. if !contract.UseGas(cost) {
  59. return nil, OutOfGasError
  60. }
  61. // Resize the memory calculated previously
  62. memory.Resize(newMemSize.Uint64())
  63. // These opcodes return an argument and are therefor handled
  64. // differently from the rest of the opcodes
  65. switch instr.op {
  66. case JUMP:
  67. if pos, err := jump(program.mapping, program.destinations, contract, stack.pop()); err != nil {
  68. return nil, err
  69. } else {
  70. *pc = pos
  71. return nil, nil
  72. }
  73. case JUMPI:
  74. pos, cond := stack.pop(), stack.pop()
  75. if cond.Cmp(common.BigTrue) >= 0 {
  76. if pos, err := jump(program.mapping, program.destinations, contract, pos); err != nil {
  77. return nil, err
  78. } else {
  79. *pc = pos
  80. return nil, nil
  81. }
  82. }
  83. case RETURN:
  84. offset, size := stack.pop(), stack.pop()
  85. return memory.GetPtr(offset.Int64(), size.Int64()), nil
  86. default:
  87. if instr.fn == nil {
  88. return nil, fmt.Errorf("Invalid opcode 0x%x", instr.op)
  89. }
  90. instr.fn(instr, pc, env, contract, memory, stack)
  91. }
  92. *pc++
  93. return nil, nil
  94. }
  95. func (instr instruction) halts() bool {
  96. return instr.returns
  97. }
  98. func (instr instruction) Op() OpCode {
  99. return instr.op
  100. }
  101. func opStaticJump(instr instruction, pc *uint64, ret *big.Int, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  102. ret.Set(instr.data)
  103. }
  104. func opAdd(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  105. x, y := stack.pop(), stack.pop()
  106. stack.push(U256(x.Add(x, y)))
  107. }
  108. func opSub(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  109. x, y := stack.pop(), stack.pop()
  110. stack.push(U256(x.Sub(x, y)))
  111. }
  112. func opMul(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  113. x, y := stack.pop(), stack.pop()
  114. stack.push(U256(x.Mul(x, y)))
  115. }
  116. func opDiv(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  117. x, y := stack.pop(), stack.pop()
  118. if y.Cmp(common.Big0) != 0 {
  119. stack.push(U256(x.Div(x, y)))
  120. } else {
  121. stack.push(new(big.Int))
  122. }
  123. }
  124. func opSdiv(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  125. x, y := S256(stack.pop()), S256(stack.pop())
  126. if y.Cmp(common.Big0) == 0 {
  127. stack.push(new(big.Int))
  128. return
  129. } else {
  130. n := new(big.Int)
  131. if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
  132. n.SetInt64(-1)
  133. } else {
  134. n.SetInt64(1)
  135. }
  136. res := x.Div(x.Abs(x), y.Abs(y))
  137. res.Mul(res, n)
  138. stack.push(U256(res))
  139. }
  140. }
  141. func opMod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  142. x, y := stack.pop(), stack.pop()
  143. if y.Cmp(common.Big0) == 0 {
  144. stack.push(new(big.Int))
  145. } else {
  146. stack.push(U256(x.Mod(x, y)))
  147. }
  148. }
  149. func opSmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  150. x, y := S256(stack.pop()), S256(stack.pop())
  151. if y.Cmp(common.Big0) == 0 {
  152. stack.push(new(big.Int))
  153. } else {
  154. n := new(big.Int)
  155. if x.Cmp(common.Big0) < 0 {
  156. n.SetInt64(-1)
  157. } else {
  158. n.SetInt64(1)
  159. }
  160. res := x.Mod(x.Abs(x), y.Abs(y))
  161. res.Mul(res, n)
  162. stack.push(U256(res))
  163. }
  164. }
  165. func opExp(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  166. x, y := stack.pop(), stack.pop()
  167. stack.push(U256(x.Exp(x, y, Pow256)))
  168. }
  169. func opSignExtend(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  170. back := stack.pop()
  171. if back.Cmp(big.NewInt(31)) < 0 {
  172. bit := uint(back.Uint64()*8 + 7)
  173. num := stack.pop()
  174. mask := back.Lsh(common.Big1, bit)
  175. mask.Sub(mask, common.Big1)
  176. if common.BitTest(num, int(bit)) {
  177. num.Or(num, mask.Not(mask))
  178. } else {
  179. num.And(num, mask)
  180. }
  181. stack.push(U256(num))
  182. }
  183. }
  184. func opNot(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  185. x := stack.pop()
  186. stack.push(U256(x.Not(x)))
  187. }
  188. func opLt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  189. x, y := stack.pop(), stack.pop()
  190. if x.Cmp(y) < 0 {
  191. stack.push(big.NewInt(1))
  192. } else {
  193. stack.push(new(big.Int))
  194. }
  195. }
  196. func opGt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  197. x, y := stack.pop(), stack.pop()
  198. if x.Cmp(y) > 0 {
  199. stack.push(big.NewInt(1))
  200. } else {
  201. stack.push(new(big.Int))
  202. }
  203. }
  204. func opSlt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  205. x, y := S256(stack.pop()), S256(stack.pop())
  206. if x.Cmp(S256(y)) < 0 {
  207. stack.push(big.NewInt(1))
  208. } else {
  209. stack.push(new(big.Int))
  210. }
  211. }
  212. func opSgt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  213. x, y := S256(stack.pop()), S256(stack.pop())
  214. if x.Cmp(y) > 0 {
  215. stack.push(big.NewInt(1))
  216. } else {
  217. stack.push(new(big.Int))
  218. }
  219. }
  220. func opEq(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  221. x, y := stack.pop(), stack.pop()
  222. if x.Cmp(y) == 0 {
  223. stack.push(big.NewInt(1))
  224. } else {
  225. stack.push(new(big.Int))
  226. }
  227. }
  228. func opIszero(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  229. x := stack.pop()
  230. if x.Cmp(common.Big0) > 0 {
  231. stack.push(new(big.Int))
  232. } else {
  233. stack.push(big.NewInt(1))
  234. }
  235. }
  236. func opAnd(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  237. x, y := stack.pop(), stack.pop()
  238. stack.push(x.And(x, y))
  239. }
  240. func opOr(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  241. x, y := stack.pop(), stack.pop()
  242. stack.push(x.Or(x, y))
  243. }
  244. func opXor(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  245. x, y := stack.pop(), stack.pop()
  246. stack.push(x.Xor(x, y))
  247. }
  248. func opByte(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  249. th, val := stack.pop(), stack.pop()
  250. if th.Cmp(big.NewInt(32)) < 0 {
  251. byte := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
  252. stack.push(byte)
  253. } else {
  254. stack.push(new(big.Int))
  255. }
  256. }
  257. func opAddmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  258. x, y, z := stack.pop(), stack.pop(), stack.pop()
  259. if z.Cmp(Zero) > 0 {
  260. add := x.Add(x, y)
  261. add.Mod(add, z)
  262. stack.push(U256(add))
  263. } else {
  264. stack.push(new(big.Int))
  265. }
  266. }
  267. func opMulmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  268. x, y, z := stack.pop(), stack.pop(), stack.pop()
  269. if z.Cmp(Zero) > 0 {
  270. mul := x.Mul(x, y)
  271. mul.Mod(mul, z)
  272. stack.push(U256(mul))
  273. } else {
  274. stack.push(new(big.Int))
  275. }
  276. }
  277. func opSha3(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  278. offset, size := stack.pop(), stack.pop()
  279. hash := crypto.Keccak256(memory.Get(offset.Int64(), size.Int64()))
  280. stack.push(common.BytesToBig(hash))
  281. }
  282. func opAddress(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  283. stack.push(common.Bytes2Big(contract.Address().Bytes()))
  284. }
  285. func opBalance(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  286. addr := common.BigToAddress(stack.pop())
  287. balance := env.Db().GetBalance(addr)
  288. stack.push(new(big.Int).Set(balance))
  289. }
  290. func opOrigin(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  291. stack.push(env.Origin().Big())
  292. }
  293. func opCaller(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  294. stack.push(contract.Caller().Big())
  295. }
  296. func opCallValue(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  297. stack.push(new(big.Int).Set(contract.value))
  298. }
  299. func opCalldataLoad(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  300. stack.push(common.Bytes2Big(getData(contract.Input, stack.pop(), common.Big32)))
  301. }
  302. func opCalldataSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  303. stack.push(big.NewInt(int64(len(contract.Input))))
  304. }
  305. func opCalldataCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  306. var (
  307. mOff = stack.pop()
  308. cOff = stack.pop()
  309. l = stack.pop()
  310. )
  311. memory.Set(mOff.Uint64(), l.Uint64(), getData(contract.Input, cOff, l))
  312. }
  313. func opExtCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  314. addr := common.BigToAddress(stack.pop())
  315. l := big.NewInt(int64(env.Db().GetCodeSize(addr)))
  316. stack.push(l)
  317. }
  318. func opCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  319. l := big.NewInt(int64(len(contract.Code)))
  320. stack.push(l)
  321. }
  322. func opCodeCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  323. var (
  324. mOff = stack.pop()
  325. cOff = stack.pop()
  326. l = stack.pop()
  327. )
  328. codeCopy := getData(contract.Code, cOff, l)
  329. memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
  330. }
  331. func opExtCodeCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  332. var (
  333. addr = common.BigToAddress(stack.pop())
  334. mOff = stack.pop()
  335. cOff = stack.pop()
  336. l = stack.pop()
  337. )
  338. codeCopy := getData(env.Db().GetCode(addr), cOff, l)
  339. memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
  340. }
  341. func opGasprice(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  342. stack.push(new(big.Int).Set(contract.Price))
  343. }
  344. func opBlockhash(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  345. num := stack.pop()
  346. n := new(big.Int).Sub(env.BlockNumber(), common.Big257)
  347. if num.Cmp(n) > 0 && num.Cmp(env.BlockNumber()) < 0 {
  348. stack.push(env.GetHash(num.Uint64()).Big())
  349. } else {
  350. stack.push(new(big.Int))
  351. }
  352. }
  353. func opCoinbase(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  354. stack.push(env.Coinbase().Big())
  355. }
  356. func opTimestamp(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  357. stack.push(U256(new(big.Int).Set(env.Time())))
  358. }
  359. func opNumber(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  360. stack.push(U256(new(big.Int).Set(env.BlockNumber())))
  361. }
  362. func opDifficulty(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  363. stack.push(U256(new(big.Int).Set(env.Difficulty())))
  364. }
  365. func opGasLimit(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  366. stack.push(U256(new(big.Int).Set(env.GasLimit())))
  367. }
  368. func opPop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  369. stack.pop()
  370. }
  371. func opPush(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  372. stack.push(new(big.Int).Set(instr.data))
  373. }
  374. func opDup(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  375. stack.dup(int(instr.data.Int64()))
  376. }
  377. func opSwap(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  378. stack.swap(int(instr.data.Int64()))
  379. }
  380. func opLog(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  381. n := int(instr.data.Int64())
  382. topics := make([]common.Hash, n)
  383. mStart, mSize := stack.pop(), stack.pop()
  384. for i := 0; i < n; i++ {
  385. topics[i] = common.BigToHash(stack.pop())
  386. }
  387. d := memory.Get(mStart.Int64(), mSize.Int64())
  388. log := NewLog(contract.Address(), topics, d, env.BlockNumber().Uint64())
  389. env.AddLog(log)
  390. }
  391. func opMload(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  392. offset := stack.pop()
  393. val := common.BigD(memory.Get(offset.Int64(), 32))
  394. stack.push(val)
  395. }
  396. func opMstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  397. // pop value of the stack
  398. mStart, val := stack.pop(), stack.pop()
  399. memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
  400. }
  401. func opMstore8(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  402. off, val := stack.pop().Int64(), stack.pop().Int64()
  403. memory.store[off] = byte(val & 0xff)
  404. }
  405. func opSload(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  406. loc := common.BigToHash(stack.pop())
  407. val := env.Db().GetState(contract.Address(), loc).Big()
  408. stack.push(val)
  409. }
  410. func opSstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  411. loc := common.BigToHash(stack.pop())
  412. val := stack.pop()
  413. env.Db().SetState(contract.Address(), loc, common.BigToHash(val))
  414. }
  415. func opJump(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  416. }
  417. func opJumpi(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  418. }
  419. func opJumpdest(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  420. }
  421. func opPc(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  422. stack.push(new(big.Int).Set(instr.data))
  423. }
  424. func opMsize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  425. stack.push(big.NewInt(int64(memory.Len())))
  426. }
  427. func opGas(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  428. stack.push(new(big.Int).Set(contract.Gas))
  429. }
  430. func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  431. var (
  432. value = stack.pop()
  433. offset, size = stack.pop(), stack.pop()
  434. input = memory.Get(offset.Int64(), size.Int64())
  435. gas = new(big.Int).Set(contract.Gas)
  436. )
  437. contract.UseGas(contract.Gas)
  438. _, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
  439. // Push item on the stack based on the returned error. If the ruleset is
  440. // homestead we must check for CodeStoreOutOfGasError (homestead only
  441. // rule) and treat as an error, if the ruleset is frontier we must
  442. // ignore this error and pretend the operation was successful.
  443. if env.RuleSet().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
  444. stack.push(new(big.Int))
  445. } else if suberr != nil && suberr != CodeStoreOutOfGasError {
  446. stack.push(new(big.Int))
  447. } else {
  448. stack.push(addr.Big())
  449. }
  450. }
  451. func opCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  452. gas := stack.pop()
  453. // pop gas and value of the stack.
  454. addr, value := stack.pop(), stack.pop()
  455. value = U256(value)
  456. // pop input size and offset
  457. inOffset, inSize := stack.pop(), stack.pop()
  458. // pop return size and offset
  459. retOffset, retSize := stack.pop(), stack.pop()
  460. address := common.BigToAddress(addr)
  461. // Get the arguments from the memory
  462. args := memory.Get(inOffset.Int64(), inSize.Int64())
  463. if len(value.Bytes()) > 0 {
  464. gas.Add(gas, params.CallStipend)
  465. }
  466. ret, err := env.Call(contract, address, args, gas, contract.Price, value)
  467. if err != nil {
  468. stack.push(new(big.Int))
  469. } else {
  470. stack.push(big.NewInt(1))
  471. memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
  472. }
  473. }
  474. func opCallCode(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  475. gas := stack.pop()
  476. // pop gas and value of the stack.
  477. addr, value := stack.pop(), stack.pop()
  478. value = U256(value)
  479. // pop input size and offset
  480. inOffset, inSize := stack.pop(), stack.pop()
  481. // pop return size and offset
  482. retOffset, retSize := stack.pop(), stack.pop()
  483. address := common.BigToAddress(addr)
  484. // Get the arguments from the memory
  485. args := memory.Get(inOffset.Int64(), inSize.Int64())
  486. if len(value.Bytes()) > 0 {
  487. gas.Add(gas, params.CallStipend)
  488. }
  489. ret, err := env.CallCode(contract, address, args, gas, contract.Price, value)
  490. if err != nil {
  491. stack.push(new(big.Int))
  492. } else {
  493. stack.push(big.NewInt(1))
  494. memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
  495. }
  496. }
  497. func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  498. gas, to, inOffset, inSize, outOffset, outSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
  499. toAddr := common.BigToAddress(to)
  500. args := memory.Get(inOffset.Int64(), inSize.Int64())
  501. ret, err := env.DelegateCall(contract, toAddr, args, gas, contract.Price)
  502. if err != nil {
  503. stack.push(new(big.Int))
  504. } else {
  505. stack.push(big.NewInt(1))
  506. memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
  507. }
  508. }
  509. func opReturn(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  510. }
  511. func opStop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  512. }
  513. func opSuicide(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  514. balance := env.Db().GetBalance(contract.Address())
  515. env.Db().AddBalance(common.BigToAddress(stack.pop()), balance)
  516. env.Db().Delete(contract.Address())
  517. }
  518. // following functions are used by the instruction jump table
  519. // make log instruction function
  520. func makeLog(size int) instrFn {
  521. return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  522. topics := make([]common.Hash, size)
  523. mStart, mSize := stack.pop(), stack.pop()
  524. for i := 0; i < size; i++ {
  525. topics[i] = common.BigToHash(stack.pop())
  526. }
  527. d := memory.Get(mStart.Int64(), mSize.Int64())
  528. log := NewLog(contract.Address(), topics, d, env.BlockNumber().Uint64())
  529. env.AddLog(log)
  530. }
  531. }
  532. // make push instruction function
  533. func makePush(size uint64, bsize *big.Int) instrFn {
  534. return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  535. byts := getData(contract.Code, new(big.Int).SetUint64(*pc+1), bsize)
  536. stack.push(common.Bytes2Big(byts))
  537. *pc += size
  538. }
  539. }
  540. // make push instruction function
  541. func makeDup(size int64) instrFn {
  542. return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  543. stack.dup(int(size))
  544. }
  545. }
  546. // make swap instruction function
  547. func makeSwap(size int64) instrFn {
  548. // switch n + 1 otherwise n would be swapped with n
  549. size += 1
  550. return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
  551. stack.swap(int(size))
  552. }
  553. }