virtual MoveInfo getMove() { if (!visited(creature->getPosition())) updateMem(creature->getPosition()); optional<Position> target; double val = 0.0001; if (Random.roll(2)) return {val, creature->wait()}; for (Position pos : creature->getPosition().neighbors8(Random)) { if (!visited(pos) && creature->move(pos)) { target = pos; break; } } if (!target) for (Position pos: creature->getPosition().neighbors8(Random)) if (creature->move(pos)) { target = pos; break; } if (!target) return {val, creature->wait() }; else return {val, creature->move(*target).append([=] (Creature* creature) { updateMem(creature->getPosition()); })}; }
void VM::logGasMem() { unsigned n = (unsigned) m_OP - (unsigned) Instruction::LOG0; constexpr int64_t logDataGas = VMSchedule::logDataGas; m_runGas = toInt63( VMSchedule::logGas + VMSchedule::logTopicGas * n + logDataGas * u512(m_SP[1])); updateMem(memNeed(m_SP[0], m_SP[1])); }
NEXT CASE(MSTORE8) { ON_OP(); updateMem(toInt63(m_SP[0]) + 1); updateIOGas(); m_mem[(unsigned)m_SP[0]] = (byte)(m_SP[1] & 0xff); }
NEXT CASE(MSTORE) { ON_OP(); updateMem(toInt63(m_SP[0]) + 32); updateIOGas(); *(h256*)&m_mem[(unsigned)m_SP[0]] = (h256)m_SP[1]; }
NEXT CASE(CODECOPY) { ON_OP(); m_copyMemSize = toInt63(m_SP[2]); updateMem(memNeed(m_SP[0], m_SP[2])); updateIOGas(); copyDataToMemory({m_pCode, m_codeSize}, m_SP); }
NEXT CASE(CALLDATACOPY) { ON_OP(); m_copyMemSize = toInt63(m_SP[2]); updateMem(memNeed(m_SP[0], m_SP[2])); updateIOGas(); bytesConstRef data{m_message->input_data, m_message->input_size}; copyDataToMemory(data, m_SP); }
virtual MoveInfo getMove() { if (!visited(creature->getPosition())) updateMem(creature->getPosition()); Vec2 direction(0, 0); double val = 0.0001; Vec2 pos = creature->getPosition(); for (Vec2 dir : Vec2::directions8(true)) if (!visited(pos + dir) && creature->canMove(dir)) { direction = dir; break; } if (direction == Vec2(0, 0)) for (Vec2 dir : Vec2::directions8(true)) if (creature->canMove(dir)) { direction = dir; break; } if (direction == Vec2(0, 0)) return {val, [this]() { creature->wait(); }}; else return {val, [this, direction]() { creature->move(direction); updateMem(creature->getPosition());}}; }
BREAK CASE(RETURN) { ON_OP(); m_copyMemSize = 0; updateMem(memNeed(m_SP[0], m_SP[1])); updateIOGas(); uint64_t b = (uint64_t)m_SP[0]; uint64_t s = (uint64_t)m_SP[1]; m_output = owning_bytes_ref{std::move(m_mem), b, s}; m_bounce = 0; }
NEXT CASE(SHA3) { ON_OP(); constexpr int64_t sha3Gas = VMSchedule::sha3Gas; constexpr int64_t sha3WordGas = VMSchedule::sha3WordGas; m_runGas = toInt63(sha3Gas + (u512(m_SP[1]) + 31) / 32 * sha3WordGas); updateMem(memNeed(m_SP[0], m_SP[1])); updateIOGas(); uint64_t inOff = (uint64_t)m_SP[0]; uint64_t inSize = (uint64_t)m_SP[1]; m_SPP[0] = (u256)sha3(bytesConstRef(m_mem.data() + inOff, inSize)); }
BREAK // // instructions potentially expanding memory // CASE(MLOAD) { ON_OP(); updateMem(toInt63(m_SP[0]) + 32); updateIOGas(); m_SPP[0] = (u256)*(h256 const*)(m_mem.data() + (unsigned)m_SP[0]); }
NEXT CASE(RETURNDATACOPY) { ON_OP(); if (m_rev < EVMC_BYZANTIUM) throwBadInstruction(); bigint const endOfAccess = bigint(m_SP[1]) + bigint(m_SP[2]); if (m_returnData.size() < endOfAccess) throwBufferOverrun(endOfAccess); m_copyMemSize = toInt63(m_SP[2]); updateMem(memNeed(m_SP[0], m_SP[2])); updateIOGas(); copyDataToMemory(&m_returnData, m_SP); }
BREAK CASE(REVERT) { // Pre-byzantium if (m_rev < EVMC_BYZANTIUM) throwBadInstruction(); ON_OP(); m_copyMemSize = 0; updateMem(memNeed(m_SP[0], m_SP[1])); updateIOGas(); uint64_t b = (uint64_t)m_SP[0]; uint64_t s = (uint64_t)m_SP[1]; owning_bytes_ref output{std::move(m_mem), b, s}; throwRevertInstruction(std::move(output)); }
NEXT CASE(EXTCODECOPY) { ON_OP(); m_runGas = m_rev >= EVMC_TANGERINE_WHISTLE ? 700 : 20; uint64_t copyMemSize = toInt63(m_SP[3]); m_copyMemSize = copyMemSize; updateMem(memNeed(m_SP[1], m_SP[3])); updateIOGas(); evmc_address address = toEvmC(asAddress(m_SP[0])); size_t memoryOffset = static_cast<size_t>(m_SP[1]); constexpr size_t codeOffsetMax = std::numeric_limits<size_t>::max(); size_t codeOffset = m_SP[2] > codeOffsetMax ? codeOffsetMax : static_cast<size_t>(m_SP[2]); size_t size = static_cast<size_t>(copyMemSize); size_t numCopied = m_context->host->copy_code( m_context, &address, codeOffset, &m_mem[memoryOffset], size); std::fill_n(&m_mem[memoryOffset + numCopied], size - numCopied, 0); }