| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660 |
- // Copyright 2015 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package vm
- import (
- "fmt"
- "math/big"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/params"
- )
- type programInstruction interface {
- // executes the program instruction and allows the instruction to modify the state of the program
- do(program *Program, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
- // returns whether the program instruction halts the execution of the JIT
- halts() bool
- // Returns the current op code (debugging purposes)
- Op() OpCode
- }
- type instrFn func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack)
- type instruction struct {
- op OpCode
- pc uint64
- fn instrFn
- data *big.Int
- gas *big.Int
- spop int
- spush int
- returns bool
- }
- func jump(mapping map[uint64]uint64, destinations map[uint64]struct{}, contract *Contract, to *big.Int) (uint64, error) {
- if !validDest(destinations, to) {
- nop := contract.GetOp(to.Uint64())
- return 0, fmt.Errorf("invalid jump destination (%v) %v", nop, to)
- }
- return mapping[to.Uint64()], nil
- }
- func (instr instruction) do(program *Program, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // calculate the new memory size and gas price for the current executing opcode
- newMemSize, cost, err := jitCalculateGasAndSize(env, contract, instr, env.Db(), memory, stack)
- if err != nil {
- return nil, err
- }
- // Use the calculated gas. When insufficient gas is present, use all gas and return an
- // Out Of Gas error
- if !contract.UseGas(cost) {
- return nil, OutOfGasError
- }
- // Resize the memory calculated previously
- memory.Resize(newMemSize.Uint64())
- // These opcodes return an argument and are therefor handled
- // differently from the rest of the opcodes
- switch instr.op {
- case JUMP:
- if pos, err := jump(program.mapping, program.destinations, contract, stack.pop()); err != nil {
- return nil, err
- } else {
- *pc = pos
- return nil, nil
- }
- case JUMPI:
- pos, cond := stack.pop(), stack.pop()
- if cond.Cmp(common.BigTrue) >= 0 {
- if pos, err := jump(program.mapping, program.destinations, contract, pos); err != nil {
- return nil, err
- } else {
- *pc = pos
- return nil, nil
- }
- }
- case RETURN:
- offset, size := stack.pop(), stack.pop()
- return memory.GetPtr(offset.Int64(), size.Int64()), nil
- default:
- if instr.fn == nil {
- return nil, fmt.Errorf("Invalid opcode 0x%x", instr.op)
- }
- instr.fn(instr, pc, env, contract, memory, stack)
- }
- *pc++
- return nil, nil
- }
- func (instr instruction) halts() bool {
- return instr.returns
- }
- func (instr instruction) Op() OpCode {
- return instr.op
- }
- func opStaticJump(instr instruction, pc *uint64, ret *big.Int, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- ret.Set(instr.data)
- }
- func opAdd(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(U256(x.Add(x, y)))
- }
- func opSub(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(U256(x.Sub(x, y)))
- }
- func opMul(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(U256(x.Mul(x, y)))
- }
- func opDiv(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- if y.Cmp(common.Big0) != 0 {
- stack.push(U256(x.Div(x, y)))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opSdiv(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := S256(stack.pop()), S256(stack.pop())
- if y.Cmp(common.Big0) == 0 {
- stack.push(new(big.Int))
- return
- } else {
- n := new(big.Int)
- if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
- n.SetInt64(-1)
- } else {
- n.SetInt64(1)
- }
- res := x.Div(x.Abs(x), y.Abs(y))
- res.Mul(res, n)
- stack.push(U256(res))
- }
- }
- func opMod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- if y.Cmp(common.Big0) == 0 {
- stack.push(new(big.Int))
- } else {
- stack.push(U256(x.Mod(x, y)))
- }
- }
- func opSmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := S256(stack.pop()), S256(stack.pop())
- if y.Cmp(common.Big0) == 0 {
- stack.push(new(big.Int))
- } else {
- n := new(big.Int)
- if x.Cmp(common.Big0) < 0 {
- n.SetInt64(-1)
- } else {
- n.SetInt64(1)
- }
- res := x.Mod(x.Abs(x), y.Abs(y))
- res.Mul(res, n)
- stack.push(U256(res))
- }
- }
- func opExp(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(U256(x.Exp(x, y, Pow256)))
- }
- func opSignExtend(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- back := stack.pop()
- if back.Cmp(big.NewInt(31)) < 0 {
- bit := uint(back.Uint64()*8 + 7)
- num := stack.pop()
- mask := back.Lsh(common.Big1, bit)
- mask.Sub(mask, common.Big1)
- if common.BitTest(num, int(bit)) {
- num.Or(num, mask.Not(mask))
- } else {
- num.And(num, mask)
- }
- stack.push(U256(num))
- }
- }
- func opNot(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x := stack.pop()
- stack.push(U256(x.Not(x)))
- }
- func opLt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- if x.Cmp(y) < 0 {
- stack.push(big.NewInt(1))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opGt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- if x.Cmp(y) > 0 {
- stack.push(big.NewInt(1))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opSlt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := S256(stack.pop()), S256(stack.pop())
- if x.Cmp(S256(y)) < 0 {
- stack.push(big.NewInt(1))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opSgt(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := S256(stack.pop()), S256(stack.pop())
- if x.Cmp(y) > 0 {
- stack.push(big.NewInt(1))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opEq(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- if x.Cmp(y) == 0 {
- stack.push(big.NewInt(1))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opIszero(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x := stack.pop()
- if x.Cmp(common.Big0) > 0 {
- stack.push(new(big.Int))
- } else {
- stack.push(big.NewInt(1))
- }
- }
- func opAnd(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.And(x, y))
- }
- func opOr(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.Or(x, y))
- }
- func opXor(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.Xor(x, y))
- }
- func opByte(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- th, val := stack.pop(), stack.pop()
- if th.Cmp(big.NewInt(32)) < 0 {
- byte := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
- stack.push(byte)
- } else {
- stack.push(new(big.Int))
- }
- }
- func opAddmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(Zero) > 0 {
- add := x.Add(x, y)
- add.Mod(add, z)
- stack.push(U256(add))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opMulmod(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
- if z.Cmp(Zero) > 0 {
- mul := x.Mul(x, y)
- mul.Mod(mul, z)
- stack.push(U256(mul))
- } else {
- stack.push(new(big.Int))
- }
- }
- func opSha3(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- offset, size := stack.pop(), stack.pop()
- hash := crypto.Keccak256(memory.Get(offset.Int64(), size.Int64()))
- stack.push(common.BytesToBig(hash))
- }
- func opAddress(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(common.Bytes2Big(contract.Address().Bytes()))
- }
- func opBalance(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- addr := common.BigToAddress(stack.pop())
- balance := env.Db().GetBalance(addr)
- stack.push(new(big.Int).Set(balance))
- }
- func opOrigin(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(env.Origin().Big())
- }
- func opCaller(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(contract.Caller().Big())
- }
- func opCallValue(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(new(big.Int).Set(contract.value))
- }
- func opCalldataLoad(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(common.Bytes2Big(getData(contract.Input, stack.pop(), common.Big32)))
- }
- func opCalldataSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(big.NewInt(int64(len(contract.Input))))
- }
- func opCalldataCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- var (
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
- )
- memory.Set(mOff.Uint64(), l.Uint64(), getData(contract.Input, cOff, l))
- }
- func opExtCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- addr := common.BigToAddress(stack.pop())
- l := big.NewInt(int64(env.Db().GetCodeSize(addr)))
- stack.push(l)
- }
- func opCodeSize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- l := big.NewInt(int64(len(contract.Code)))
- stack.push(l)
- }
- func opCodeCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- var (
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
- )
- codeCopy := getData(contract.Code, cOff, l)
- memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
- }
- func opExtCodeCopy(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- var (
- addr = common.BigToAddress(stack.pop())
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
- )
- codeCopy := getData(env.Db().GetCode(addr), cOff, l)
- memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
- }
- func opGasprice(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(new(big.Int).Set(contract.Price))
- }
- func opBlockhash(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- num := stack.pop()
- n := new(big.Int).Sub(env.BlockNumber(), common.Big257)
- if num.Cmp(n) > 0 && num.Cmp(env.BlockNumber()) < 0 {
- stack.push(env.GetHash(num.Uint64()).Big())
- } else {
- stack.push(new(big.Int))
- }
- }
- func opCoinbase(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(env.Coinbase().Big())
- }
- func opTimestamp(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(U256(new(big.Int).Set(env.Time())))
- }
- func opNumber(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(U256(new(big.Int).Set(env.BlockNumber())))
- }
- func opDifficulty(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(U256(new(big.Int).Set(env.Difficulty())))
- }
- func opGasLimit(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(U256(new(big.Int).Set(env.GasLimit())))
- }
- func opPop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.pop()
- }
- func opPush(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(new(big.Int).Set(instr.data))
- }
- func opDup(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.dup(int(instr.data.Int64()))
- }
- func opSwap(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.swap(int(instr.data.Int64()))
- }
- func opLog(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- n := int(instr.data.Int64())
- topics := make([]common.Hash, n)
- mStart, mSize := stack.pop(), stack.pop()
- for i := 0; i < n; i++ {
- topics[i] = common.BigToHash(stack.pop())
- }
- d := memory.Get(mStart.Int64(), mSize.Int64())
- log := NewLog(contract.Address(), topics, d, env.BlockNumber().Uint64())
- env.AddLog(log)
- }
- func opMload(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- offset := stack.pop()
- val := common.BigD(memory.Get(offset.Int64(), 32))
- stack.push(val)
- }
- func opMstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- // pop value of the stack
- mStart, val := stack.pop(), stack.pop()
- memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
- }
- func opMstore8(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- off, val := stack.pop().Int64(), stack.pop().Int64()
- memory.store[off] = byte(val & 0xff)
- }
- func opSload(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- loc := common.BigToHash(stack.pop())
- val := env.Db().GetState(contract.Address(), loc).Big()
- stack.push(val)
- }
- func opSstore(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- loc := common.BigToHash(stack.pop())
- val := stack.pop()
- env.Db().SetState(contract.Address(), loc, common.BigToHash(val))
- }
- func opJump(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- }
- func opJumpi(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- }
- func opJumpdest(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- }
- func opPc(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(new(big.Int).Set(instr.data))
- }
- func opMsize(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(big.NewInt(int64(memory.Len())))
- }
- func opGas(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.push(new(big.Int).Set(contract.Gas))
- }
- func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- var (
- value = stack.pop()
- offset, size = stack.pop(), stack.pop()
- input = memory.Get(offset.Int64(), size.Int64())
- gas = new(big.Int).Set(contract.Gas)
- )
- contract.UseGas(contract.Gas)
- _, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
- // Push item on the stack based on the returned error. If the ruleset is
- // homestead we must check for CodeStoreOutOfGasError (homestead only
- // rule) and treat as an error, if the ruleset is frontier we must
- // ignore this error and pretend the operation was successful.
- if env.RuleSet().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
- stack.push(new(big.Int))
- } else if suberr != nil && suberr != CodeStoreOutOfGasError {
- stack.push(new(big.Int))
- } else {
- stack.push(addr.Big())
- }
- }
- func opCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- gas := stack.pop()
- // pop gas and value of the stack.
- addr, value := stack.pop(), stack.pop()
- value = U256(value)
- // pop input size and offset
- inOffset, inSize := stack.pop(), stack.pop()
- // pop return size and offset
- retOffset, retSize := stack.pop(), stack.pop()
- address := common.BigToAddress(addr)
- // Get the arguments from the memory
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- if len(value.Bytes()) > 0 {
- gas.Add(gas, params.CallStipend)
- }
- ret, err := env.Call(contract, address, args, gas, contract.Price, value)
- if err != nil {
- stack.push(new(big.Int))
- } else {
- stack.push(big.NewInt(1))
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- }
- func opCallCode(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- gas := stack.pop()
- // pop gas and value of the stack.
- addr, value := stack.pop(), stack.pop()
- value = U256(value)
- // pop input size and offset
- inOffset, inSize := stack.pop(), stack.pop()
- // pop return size and offset
- retOffset, retSize := stack.pop(), stack.pop()
- address := common.BigToAddress(addr)
- // Get the arguments from the memory
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- if len(value.Bytes()) > 0 {
- gas.Add(gas, params.CallStipend)
- }
- ret, err := env.CallCode(contract, address, args, gas, contract.Price, value)
- if err != nil {
- stack.push(new(big.Int))
- } else {
- stack.push(big.NewInt(1))
- memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
- }
- }
- func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- gas, to, inOffset, inSize, outOffset, outSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
- toAddr := common.BigToAddress(to)
- args := memory.Get(inOffset.Int64(), inSize.Int64())
- ret, err := env.DelegateCall(contract, toAddr, args, gas, contract.Price)
- if err != nil {
- stack.push(new(big.Int))
- } else {
- stack.push(big.NewInt(1))
- memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
- }
- }
- func opReturn(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- }
- func opStop(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- }
- func opSuicide(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- balance := env.Db().GetBalance(contract.Address())
- env.Db().AddBalance(common.BigToAddress(stack.pop()), balance)
- env.Db().Delete(contract.Address())
- }
- // following functions are used by the instruction jump table
- // make log instruction function
- func makeLog(size int) instrFn {
- return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- topics := make([]common.Hash, size)
- mStart, mSize := stack.pop(), stack.pop()
- for i := 0; i < size; i++ {
- topics[i] = common.BigToHash(stack.pop())
- }
- d := memory.Get(mStart.Int64(), mSize.Int64())
- log := NewLog(contract.Address(), topics, d, env.BlockNumber().Uint64())
- env.AddLog(log)
- }
- }
- // make push instruction function
- func makePush(size uint64, bsize *big.Int) instrFn {
- return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- byts := getData(contract.Code, new(big.Int).SetUint64(*pc+1), bsize)
- stack.push(common.Bytes2Big(byts))
- *pc += size
- }
- }
- // make push instruction function
- func makeDup(size int64) instrFn {
- return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.dup(int(size))
- }
- }
- // make swap instruction function
- func makeSwap(size int64) instrFn {
- // switch n + 1 otherwise n would be swapped with n
- size += 1
- return func(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *Stack) {
- stack.swap(int(size))
- }
- }
|