diff --git a/libevmjit-cpp/Env.cpp b/libevmjit-cpp/Env.cpp index 4112774ee..9fa15735e 100644 --- a/libevmjit-cpp/Env.cpp +++ b/libevmjit-cpp/Env.cpp @@ -42,6 +42,11 @@ extern "C" *o_value = eth2llvm(u); } + EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash) + { + *o_hash = _env->prevhash(llvm2eth(*_number)); + } + EXPORT void env_create(ExtVMFace* _env, i256* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address) { auto endowment = llvm2eth(*_endowment); diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 6f256a571..7733321aa 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -645,6 +645,14 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode break; } + case Instruction::BLOCKHASH: + { + auto number = stack.pop(); + auto hash = _ext.blockhash(number); + stack.push(hash); + break; + } + case Instruction::BALANCE: { auto address = stack.pop(); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index f2db32137..c30b0a1e3 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -45,6 +45,7 @@ std::array::value> const& getEnvFuncDescs() FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})}, FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})}, FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})}, + FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, FuncDesc{"env_getExtCode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, FuncDesc{"ext_calldataload", getFunctionType(Type::Void, {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr})}, }}; @@ -117,6 +118,14 @@ llvm::Value* Ext::balance(llvm::Value* _address) return m_builder.CreateLoad(ret); } +llvm::Value* Ext::blockhash(llvm::Value* _number) +{ + auto hash = getArgAlloca(); + createCall(EnvFunc::blockhash, {getRuntimeManager().getEnvPtr(), byPtr(_number), hash}); + hash = m_builder.CreateLoad(hash); + return Endianness::toNative(getBuilder(), hash); +} + llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) { auto gas = byPtr(_gas); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 9a9b3548a..2850be072 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -33,6 +33,7 @@ enum class EnvFunc create, call, log, + blockhash, getExtCode, calldataload, // Helper function, not client Env interface @@ -51,6 +52,7 @@ public: llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress); + llvm::Value* blockhash(llvm::Value* _number); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); MemoryRef getExtCode(llvm::Value* _addr);