github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/core/vm/instructions.go (about) 1 // Copyright 2014 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 17 package vm 18 19 import ( 20 "math/big" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core/state" 24 "github.com/ethereum/go-ethereum/crypto" 25 "github.com/ethereum/go-ethereum/params" 26 ) 27 28 type instrFn func(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) 29 type instrExFn func(instr instruction, ret *big.Int, env Environment, context *Context, memory *Memory, stack *stack) 30 31 type instruction struct { 32 op OpCode 33 pc uint64 34 fn instrFn 35 specFn instrExFn 36 data *big.Int 37 38 gas *big.Int 39 spop int 40 spush int 41 } 42 43 func opStaticJump(instr instruction, ret *big.Int, env Environment, context *Context, memory *Memory, stack *stack) { 44 ret.Set(instr.data) 45 } 46 47 func opAdd(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 48 x, y := stack.pop(), stack.pop() 49 stack.push(U256(x.Add(x, y))) 50 } 51 52 func opSub(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 53 x, y := stack.pop(), stack.pop() 54 stack.push(U256(x.Sub(x, y))) 55 } 56 57 func opMul(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 58 x, y := stack.pop(), stack.pop() 59 stack.push(U256(x.Mul(x, y))) 60 } 61 62 func opDiv(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 63 x, y := stack.pop(), stack.pop() 64 if y.Cmp(common.Big0) != 0 { 65 stack.push(U256(x.Div(x, y))) 66 } else { 67 stack.push(new(big.Int)) 68 } 69 } 70 71 func opSdiv(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 72 x, y := S256(stack.pop()), S256(stack.pop()) 73 if y.Cmp(common.Big0) == 0 { 74 stack.push(new(big.Int)) 75 return 76 } else { 77 n := new(big.Int) 78 if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 { 79 n.SetInt64(-1) 80 } else { 81 n.SetInt64(1) 82 } 83 84 res := x.Div(x.Abs(x), y.Abs(y)) 85 res.Mul(res, n) 86 87 stack.push(U256(res)) 88 } 89 } 90 91 func opMod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 92 x, y := stack.pop(), stack.pop() 93 if y.Cmp(common.Big0) == 0 { 94 stack.push(new(big.Int)) 95 } else { 96 stack.push(U256(x.Mod(x, y))) 97 } 98 } 99 100 func opSmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 101 x, y := S256(stack.pop()), S256(stack.pop()) 102 103 if y.Cmp(common.Big0) == 0 { 104 stack.push(new(big.Int)) 105 } else { 106 n := new(big.Int) 107 if x.Cmp(common.Big0) < 0 { 108 n.SetInt64(-1) 109 } else { 110 n.SetInt64(1) 111 } 112 113 res := x.Mod(x.Abs(x), y.Abs(y)) 114 res.Mul(res, n) 115 116 stack.push(U256(res)) 117 } 118 } 119 120 func opExp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 121 x, y := stack.pop(), stack.pop() 122 stack.push(U256(x.Exp(x, y, Pow256))) 123 } 124 125 func opSignExtend(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 126 back := stack.pop() 127 if back.Cmp(big.NewInt(31)) < 0 { 128 bit := uint(back.Uint64()*8 + 7) 129 num := stack.pop() 130 mask := back.Lsh(common.Big1, bit) 131 mask.Sub(mask, common.Big1) 132 if common.BitTest(num, int(bit)) { 133 num.Or(num, mask.Not(mask)) 134 } else { 135 num.And(num, mask) 136 } 137 138 stack.push(U256(num)) 139 } 140 } 141 142 func opNot(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 143 x := stack.pop() 144 stack.push(U256(x.Not(x))) 145 } 146 147 func opLt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 148 x, y := stack.pop(), stack.pop() 149 if x.Cmp(y) < 0 { 150 stack.push(big.NewInt(1)) 151 } else { 152 stack.push(new(big.Int)) 153 } 154 } 155 156 func opGt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 157 x, y := stack.pop(), stack.pop() 158 if x.Cmp(y) > 0 { 159 stack.push(big.NewInt(1)) 160 } else { 161 stack.push(new(big.Int)) 162 } 163 } 164 165 func opSlt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 166 x, y := S256(stack.pop()), S256(stack.pop()) 167 if x.Cmp(S256(y)) < 0 { 168 stack.push(big.NewInt(1)) 169 } else { 170 stack.push(new(big.Int)) 171 } 172 } 173 174 func opSgt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 175 x, y := S256(stack.pop()), S256(stack.pop()) 176 if x.Cmp(y) > 0 { 177 stack.push(big.NewInt(1)) 178 } else { 179 stack.push(new(big.Int)) 180 } 181 } 182 183 func opEq(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 184 x, y := stack.pop(), stack.pop() 185 if x.Cmp(y) == 0 { 186 stack.push(big.NewInt(1)) 187 } else { 188 stack.push(new(big.Int)) 189 } 190 } 191 192 func opIszero(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 193 x := stack.pop() 194 if x.Cmp(common.Big0) > 0 { 195 stack.push(new(big.Int)) 196 } else { 197 stack.push(big.NewInt(1)) 198 } 199 } 200 201 func opAnd(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 202 x, y := stack.pop(), stack.pop() 203 stack.push(x.And(x, y)) 204 } 205 func opOr(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 206 x, y := stack.pop(), stack.pop() 207 stack.push(x.Or(x, y)) 208 } 209 func opXor(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 210 x, y := stack.pop(), stack.pop() 211 stack.push(x.Xor(x, y)) 212 } 213 func opByte(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 214 th, val := stack.pop(), stack.pop() 215 if th.Cmp(big.NewInt(32)) < 0 { 216 byte := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()])) 217 stack.push(byte) 218 } else { 219 stack.push(new(big.Int)) 220 } 221 } 222 func opAddmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 223 x, y, z := stack.pop(), stack.pop(), stack.pop() 224 if z.Cmp(Zero) > 0 { 225 add := x.Add(x, y) 226 add.Mod(add, z) 227 stack.push(U256(add)) 228 } else { 229 stack.push(new(big.Int)) 230 } 231 } 232 func opMulmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 233 x, y, z := stack.pop(), stack.pop(), stack.pop() 234 if z.Cmp(Zero) > 0 { 235 mul := x.Mul(x, y) 236 mul.Mod(mul, z) 237 stack.push(U256(mul)) 238 } else { 239 stack.push(new(big.Int)) 240 } 241 } 242 243 func opSha3(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 244 offset, size := stack.pop(), stack.pop() 245 hash := crypto.Sha3(memory.Get(offset.Int64(), size.Int64())) 246 247 stack.push(common.BytesToBig(hash)) 248 } 249 250 func opAddress(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 251 stack.push(common.Bytes2Big(context.Address().Bytes())) 252 } 253 254 func opBalance(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 255 addr := common.BigToAddress(stack.pop()) 256 balance := env.State().GetBalance(addr) 257 258 stack.push(new(big.Int).Set(balance)) 259 } 260 261 func opOrigin(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 262 stack.push(env.Origin().Big()) 263 } 264 265 func opCaller(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 266 stack.push(common.Bytes2Big(context.caller.Address().Bytes())) 267 } 268 269 func opCallValue(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 270 stack.push(new(big.Int).Set(context.value)) 271 } 272 273 func opCalldataLoad(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 274 stack.push(common.Bytes2Big(getData(context.Input, stack.pop(), common.Big32))) 275 } 276 277 func opCalldataSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 278 stack.push(big.NewInt(int64(len(context.Input)))) 279 } 280 281 func opCalldataCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 282 var ( 283 mOff = stack.pop() 284 cOff = stack.pop() 285 l = stack.pop() 286 ) 287 memory.Set(mOff.Uint64(), l.Uint64(), getData(context.Input, cOff, l)) 288 } 289 290 func opExtCodeSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 291 addr := common.BigToAddress(stack.pop()) 292 l := big.NewInt(int64(len(env.State().GetCode(addr)))) 293 stack.push(l) 294 } 295 296 func opCodeSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 297 l := big.NewInt(int64(len(context.Code))) 298 stack.push(l) 299 } 300 301 func opCodeCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 302 var ( 303 mOff = stack.pop() 304 cOff = stack.pop() 305 l = stack.pop() 306 ) 307 codeCopy := getData(context.Code, cOff, l) 308 309 memory.Set(mOff.Uint64(), l.Uint64(), codeCopy) 310 } 311 312 func opExtCodeCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 313 var ( 314 addr = common.BigToAddress(stack.pop()) 315 mOff = stack.pop() 316 cOff = stack.pop() 317 l = stack.pop() 318 ) 319 codeCopy := getData(env.State().GetCode(addr), cOff, l) 320 321 memory.Set(mOff.Uint64(), l.Uint64(), codeCopy) 322 } 323 324 func opGasprice(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 325 stack.push(new(big.Int).Set(context.Price)) 326 } 327 328 func opBlockhash(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 329 num := stack.pop() 330 331 n := new(big.Int).Sub(env.BlockNumber(), common.Big257) 332 if num.Cmp(n) > 0 && num.Cmp(env.BlockNumber()) < 0 { 333 stack.push(env.GetHash(num.Uint64()).Big()) 334 } else { 335 stack.push(new(big.Int)) 336 } 337 } 338 339 func opCoinbase(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 340 stack.push(env.Coinbase().Big()) 341 } 342 343 func opTimestamp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 344 stack.push(U256(new(big.Int).Set(env.Time()))) 345 } 346 347 func opNumber(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 348 stack.push(U256(new(big.Int).Set(env.BlockNumber()))) 349 } 350 351 func opDifficulty(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 352 stack.push(U256(new(big.Int).Set(env.Difficulty()))) 353 } 354 355 func opGasLimit(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 356 stack.push(U256(new(big.Int).Set(env.GasLimit()))) 357 } 358 359 func opPop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 360 stack.pop() 361 } 362 363 func opPush(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 364 stack.push(new(big.Int).Set(instr.data)) 365 } 366 367 func opDup(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 368 stack.dup(int(instr.data.Int64())) 369 } 370 371 func opSwap(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 372 stack.swap(int(instr.data.Int64())) 373 } 374 375 func opLog(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 376 n := int(instr.data.Int64()) 377 topics := make([]common.Hash, n) 378 mStart, mSize := stack.pop(), stack.pop() 379 for i := 0; i < n; i++ { 380 topics[i] = common.BigToHash(stack.pop()) 381 } 382 383 d := memory.Get(mStart.Int64(), mSize.Int64()) 384 log := state.NewLog(context.Address(), topics, d, env.BlockNumber().Uint64()) 385 env.AddLog(log) 386 } 387 388 func opMload(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 389 offset := stack.pop() 390 val := common.BigD(memory.Get(offset.Int64(), 32)) 391 stack.push(val) 392 } 393 394 func opMstore(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 395 // pop value of the stack 396 mStart, val := stack.pop(), stack.pop() 397 memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256)) 398 } 399 400 func opMstore8(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 401 off, val := stack.pop().Int64(), stack.pop().Int64() 402 memory.store[off] = byte(val & 0xff) 403 } 404 405 func opSload(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 406 loc := common.BigToHash(stack.pop()) 407 val := env.State().GetState(context.Address(), loc).Big() 408 stack.push(val) 409 } 410 411 func opSstore(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 412 loc := common.BigToHash(stack.pop()) 413 val := stack.pop() 414 415 env.State().SetState(context.Address(), loc, common.BigToHash(val)) 416 } 417 418 func opJump(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {} 419 func opJumpi(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {} 420 func opJumpdest(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {} 421 422 func opPc(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 423 stack.push(new(big.Int).Set(instr.data)) 424 } 425 426 func opMsize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 427 stack.push(big.NewInt(int64(memory.Len()))) 428 } 429 430 func opGas(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 431 stack.push(new(big.Int).Set(context.Gas)) 432 } 433 434 func opCreate(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 435 var ( 436 value = stack.pop() 437 offset, size = stack.pop(), stack.pop() 438 input = memory.Get(offset.Int64(), size.Int64()) 439 gas = new(big.Int).Set(context.Gas) 440 addr common.Address 441 ) 442 443 context.UseGas(context.Gas) 444 ret, suberr, ref := env.Create(context, input, gas, context.Price, value) 445 if suberr != nil { 446 stack.push(new(big.Int)) 447 448 } else { 449 // gas < len(ret) * Createinstr.dataGas == NO_CODE 450 dataGas := big.NewInt(int64(len(ret))) 451 dataGas.Mul(dataGas, params.CreateDataGas) 452 if context.UseGas(dataGas) { 453 ref.SetCode(ret) 454 } 455 addr = ref.Address() 456 457 stack.push(addr.Big()) 458 459 } 460 } 461 462 func opCall(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 463 gas := stack.pop() 464 // pop gas and value of the stack. 465 addr, value := stack.pop(), stack.pop() 466 value = U256(value) 467 // pop input size and offset 468 inOffset, inSize := stack.pop(), stack.pop() 469 // pop return size and offset 470 retOffset, retSize := stack.pop(), stack.pop() 471 472 address := common.BigToAddress(addr) 473 474 // Get the arguments from the memory 475 args := memory.Get(inOffset.Int64(), inSize.Int64()) 476 477 if len(value.Bytes()) > 0 { 478 gas.Add(gas, params.CallStipend) 479 } 480 481 ret, err := env.Call(context, address, args, gas, context.Price, value) 482 483 if err != nil { 484 stack.push(new(big.Int)) 485 486 } else { 487 stack.push(big.NewInt(1)) 488 489 memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 490 } 491 } 492 493 func opCallCode(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 494 gas := stack.pop() 495 // pop gas and value of the stack. 496 addr, value := stack.pop(), stack.pop() 497 value = U256(value) 498 // pop input size and offset 499 inOffset, inSize := stack.pop(), stack.pop() 500 // pop return size and offset 501 retOffset, retSize := stack.pop(), stack.pop() 502 503 address := common.BigToAddress(addr) 504 505 // Get the arguments from the memory 506 args := memory.Get(inOffset.Int64(), inSize.Int64()) 507 508 if len(value.Bytes()) > 0 { 509 gas.Add(gas, params.CallStipend) 510 } 511 512 ret, err := env.CallCode(context, address, args, gas, context.Price, value) 513 514 if err != nil { 515 stack.push(new(big.Int)) 516 517 } else { 518 stack.push(big.NewInt(1)) 519 520 memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) 521 } 522 } 523 524 func opReturn(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {} 525 func opStop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {} 526 527 func opSuicide(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { 528 receiver := env.State().GetOrNewStateObject(common.BigToAddress(stack.pop())) 529 balance := env.State().GetBalance(context.Address()) 530 531 receiver.AddBalance(balance) 532 533 env.State().Delete(context.Address()) 534 }