instructions.go 21 KB

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