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) }
// 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) } }
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 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) }
// jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for // the operation. This does not reduce gas or resizes the memory. func jitCalculateGasAndSize(env Environment, contract *Contract, instr instruction, statedb Database, mem *Memory, stack *stack) (*big.Int, *big.Int, error) { var ( gas = new(big.Int) newMemSize *big.Int = new(big.Int) ) err := jitBaseCheck(instr, stack, gas) if err != nil { return nil, nil, err } // stack Check, memory resize & gas phase switch op := instr.op; op { case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: n := int(op - SWAP1 + 2) err := stack.require(n) if err != nil { return nil, nil, err } gas.Set(GasFastestStep) case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: n := int(op - DUP1 + 1) err := stack.require(n) if err != nil { return nil, nil, err } gas.Set(GasFastestStep) case LOG0, LOG1, LOG2, LOG3, LOG4: n := int(op - LOG0) err := stack.require(n + 2) if err != nil { return nil, nil, err } mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1] add := new(big.Int) gas.Add(gas, params.LogGas) gas.Add(gas, add.Mul(big.NewInt(int64(n)), params.LogTopicGas)) gas.Add(gas, add.Mul(mSize, params.LogDataGas)) newMemSize = calcMemSize(mStart, mSize) case EXP: gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas)) case SSTORE: err := stack.require(2) if err != nil { return nil, nil, err } var g *big.Int y, x := stack.data[stack.len()-2], stack.data[stack.len()-1] val := statedb.GetState(contract.Address(), common.BigToHash(x)) // This checks for 3 scenario's and calculates gas accordingly // 1. From a zero-value address to a non-zero value (NEW VALUE) // 2. From a non-zero value address to a zero-value address (DELETE) // 3. From a nen-zero to a non-zero (CHANGE) if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) { g = params.SstoreSetGas } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { statedb.AddRefund(params.SstoreRefundGas) g = params.SstoreClearGas } else { g = params.SstoreClearGas } gas.Set(g) case SUICIDE: if !statedb.IsDeleted(contract.Address()) { statedb.AddRefund(params.SuicideRefundGas) } case MLOAD: newMemSize = calcMemSize(stack.peek(), u256(32)) case MSTORE8: newMemSize = calcMemSize(stack.peek(), u256(1)) case MSTORE: newMemSize = calcMemSize(stack.peek(), u256(32)) case RETURN: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) case SHA3: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) words := toWordSize(stack.data[stack.len()-2]) gas.Add(gas, words.Mul(words, params.Sha3WordGas)) case CALLDATACOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) gas.Add(gas, words.Mul(words, params.CopyGas)) case CODECOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) gas.Add(gas, words.Mul(words, params.CopyGas)) case EXTCODECOPY: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) words := toWordSize(stack.data[stack.len()-4]) gas.Add(gas, words.Mul(words, params.CopyGas)) case CREATE: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) case CALL, CALLCODE: gas.Add(gas, stack.data[stack.len()-1]) if op == CALL { //if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil { if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) { gas.Add(gas, params.CallNewAccountGas) } } if len(stack.data[stack.len()-3].Bytes()) > 0 { gas.Add(gas, params.CallValueTransferGas) } x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5]) newMemSize = common.BigMax(x, y) } quadMemGas(mem, newMemSize, gas) return newMemSize, gas, nil }