#include #include #include #include #include #include #include "../libevmjit/Utils.h" extern "C" { #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else #define EXPORT #endif using namespace dev; using namespace dev::eth; using jit::i256; using jit::eth2llvm; EXPORT void ext_store(ExtVMFace* _env, i256* _index, i256* o_value) { auto index = llvm2eth(*_index); auto value = _env->store(index); // Interface uses native endianness *o_value = eth2llvm(value); } EXPORT void ext_setStore(ExtVMFace* _env, i256* _index, i256* _value) { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); if (value == 0 && _env->store(index) != 0) // If delete _env->sub.refunds += c_sstoreRefundGas; // Increase refund counter _env->setStore(index, value); // Interface uses native endianness } EXPORT void ext_calldataload(ExtVMFace* _env, i256* _index, ::byte* o_value) { auto index = static_cast(llvm2eth(*_index)); assert(index + 31 > index); // TODO: Handle large index for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) o_value[j] = i < _env->data.size() ? _env->data[i] : 0; // Keep Big Endian // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } EXPORT void ext_balance(ExtVMFace* _env, h256* _address, i256* o_value) { auto u = _env->balance(right160(*_address)); *o_value = eth2llvm(u); } EXPORT void ext_suicide(ExtVMFace* _env, h256 const* _address) { _env->suicide(right160(*_address)); } EXPORT void ext_create(ExtVMFace* _env, i256* _endowment, i256* _initOff, i256* _initSize, h256* o_address) { auto endowment = llvm2eth(*_endowment); if (_env->balance(_env->myAddress) >= endowment) { _env->subBalance(endowment); u256 gas; // TODO: Handle gas auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); //auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); auto initRef = bytesConstRef(); // FIXME: Handle memory OnOpFunc onOp {}; // TODO: Handle that thing h256 address(_env->create(endowment, &gas, initRef, onOp), h256::AlignRight); *o_address = address; } else *o_address = {}; } EXPORT void ext_call(ExtVMFace* _env, i256* io_gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* o_ret) { auto&& ext = *_env; auto value = llvm2eth(*_value); auto ret = false; auto gas = llvm2eth(*io_gas); if (ext.balance(ext.myAddress) >= value) { ext.subBalance(value); auto receiveAddress = right160(*_receiveAddress); auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); auto outOff = static_cast(llvm2eth(*_outOff)); auto outSize = static_cast(llvm2eth(*_outSize)); //auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); //auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); auto inRef = bytesConstRef(); // FIXME: Handle memory auto outRef = bytesConstRef(); // FIXME: Handle memory OnOpFunc onOp {}; // TODO: Handle that thing auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); } *io_gas = eth2llvm(gas); o_ret->a = ret ? 1 : 0; } EXPORT void ext_sha3(byte* _begin, uint64_t _size, h256* o_hash) { auto hash = sha3({_begin, _size}); *o_hash = hash; } EXPORT unsigned char* ext_codeAt(ExtVMFace* _env, h256* _addr256) { auto addr = right160(*_addr256); auto& code = _env->codeAt(addr); return const_cast(code.data()); } EXPORT void ext_codesizeAt(ExtVMFace* _env, h256* _addr256, i256* o_ret) { auto addr = right160(*_addr256); auto& code = _env->codeAt(addr); *o_ret = eth2llvm(u256(code.size())); } void ext_show_bytes(bytesConstRef _bytes) { for (auto b : _bytes) std::cerr << std::hex << std::setw(2) << std::setfill('0') << static_cast(b) << " "; std::cerr << std::endl; } EXPORT void ext_log0(ExtVMFace* _env, i256* _memIdx, i256* _numBytes) { auto memIdx = llvm2eth(*_memIdx).convert_to(); auto numBytes = llvm2eth(*_numBytes).convert_to(); //auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); auto dataRef = bytesConstRef(); // FIXME: Handle memory _env->log({}, dataRef); } EXPORT void ext_log1(ExtVMFace* _env, i256* _memIdx, i256* _numBytes, i256* _topic1) { auto memIdx = static_cast(llvm2eth(*_memIdx)); auto numBytes = static_cast(llvm2eth(*_numBytes)); auto topic1 = llvm2eth(*_topic1); //auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); auto dataRef = bytesConstRef(); // FIXME: Handle memory _env->log({topic1}, dataRef); } EXPORT void ext_log2(ExtVMFace* _env, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2) { auto memIdx = static_cast(llvm2eth(*_memIdx)); auto numBytes = static_cast(llvm2eth(*_numBytes)); auto topic1 = llvm2eth(*_topic1); auto topic2 = llvm2eth(*_topic2); //auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); auto dataRef = bytesConstRef(); // FIXME: Handle memory _env->log({ topic1, topic2 }, dataRef); } EXPORT void ext_log3(ExtVMFace* _env, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3) { auto memIdx = static_cast(llvm2eth(*_memIdx)); auto numBytes = static_cast(llvm2eth(*_numBytes)); auto topic1 = llvm2eth(*_topic1); auto topic2 = llvm2eth(*_topic2); auto topic3 = llvm2eth(*_topic3); //auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); auto dataRef = bytesConstRef(); // FIXME: Handle memory _env->log({ topic1, topic2, topic3 }, dataRef); } EXPORT void ext_log4(ExtVMFace* _env, i256* _memIdx, i256* _numBytes, i256* _topic1, i256* _topic2, i256* _topic3, i256* _topic4) { auto memIdx = static_cast(llvm2eth(*_memIdx)); auto numBytes = static_cast(llvm2eth(*_numBytes)); auto topic1 = llvm2eth(*_topic1); auto topic2 = llvm2eth(*_topic2); auto topic3 = llvm2eth(*_topic3); auto topic4 = llvm2eth(*_topic4); //auto dataRef = bytesConstRef(_rt->getMemory().data() + memIdx, numBytes); auto dataRef = bytesConstRef(); // FIXME: Handle memory _env->log({ topic1, topic2, topic3, topic4 }, dataRef); } }