Browse Source

Try to throw an OutOfGas exception when out of gas. The exception cannot be handled.

[#80660432]
cl-refactor
Paweł Bylica 10 years ago
parent
commit
dbb3e81bdf
  1. 23
      evmcc/ExecutionEngine.cpp
  2. 20
      evmcc/GasMeter.cpp
  3. 1
      evmcc/GasMeter.h
  4. 17
      evmcc/Runtime.cpp
  5. 1
      evmcc/Type.h

23
evmcc/ExecutionEngine.cpp

@ -13,6 +13,8 @@
#include <llvm/Support/PrettyStackTrace.h> #include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Host.h> #include <llvm/Support/Host.h>
#include <libevm/VM.h>
#include "Runtime.h" #include "Runtime.h"
#include "Memory.h" #include "Memory.h"
#include "Type.h" #include "Type.h"
@ -87,7 +89,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
ext->data = calldata; ext->data = calldata;
// Init runtime // Init runtime
uint64_t gas = 1000000; uint64_t gas = 100;
Runtime runtime(gas, std::move(ext)); Runtime runtime(gas, std::move(ext));
auto entryFunc = module->getFunction("main"); auto entryFunc = module->getFunction("main");
@ -97,9 +99,20 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
exit(1); exit(1);
} }
auto result = exec->runFunction(entryFunc, {});
ReturnCode returnCode;
try
{
auto result = exec->runFunction(entryFunc, {});
returnCode = static_cast<ReturnCode>(result.IntVal.getZExtValue());
}
catch (const dev::eth::OutOfGas&)
{
returnCode = ReturnCode::OutOfGas;
}
gas = static_cast<decltype(gas)>(Runtime::getGas()); gas = static_cast<decltype(gas)>(Runtime::getGas());
auto returnCode = static_cast<ReturnCode>(result.IntVal.getZExtValue());
if (returnCode == ReturnCode::Return) if (returnCode == ReturnCode::Return)
{ {
auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface
@ -108,10 +121,8 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
std::cout << "]\n"; std::cout << "]\n";
return 10;
} }
return 0; return static_cast<int>(returnCode);
} }
} }

20
evmcc/GasMeter.cpp

@ -83,11 +83,27 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas");
m_gas->setUnnamedAddr(true); // Address is not important m_gas->setUnnamedAddr(true); // Address is not important
m_rtExit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::MainReturn, false), llvm::Function::ExternalLinkage, "rt_exit", _module);
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module);
InsertPointGuard guard(m_builder); InsertPointGuard guard(m_builder);
m_builder.SetInsertPoint(llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc));
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc);
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc);
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc);
m_builder.SetInsertPoint(checkBB);
llvm::Value* cost = m_gasCheckFunc->arg_begin(); llvm::Value* cost = m_gasCheckFunc->arg_begin();
llvm::Value* gas = m_builder.CreateLoad(m_gas); cost->setName("cost");
llvm::Value* gas = m_builder.CreateLoad(m_gas, "gas");
auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas");
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
m_builder.SetInsertPoint(outOfGasBB);
m_builder.CreateCall(m_rtExit, Constant::get(ReturnCode::OutOfGas));
m_builder.CreateRetVoid();
m_builder.SetInsertPoint(updateBB);
gas = m_builder.CreateSub(gas, cost); gas = m_builder.CreateSub(gas, cost);
m_builder.CreateStore(gas, m_gas); m_builder.CreateStore(gas, m_gas);
m_builder.CreateRetVoid(); m_builder.CreateRetVoid();

1
evmcc/GasMeter.h

@ -41,6 +41,7 @@ private:
llvm::IRBuilder<>& m_builder; llvm::IRBuilder<>& m_builder;
llvm::CallInst* m_checkCall = nullptr; llvm::CallInst* m_checkCall = nullptr;
llvm::GlobalVariable* m_gas; llvm::GlobalVariable* m_gas;
llvm::Function* m_rtExit;
llvm::Function* m_gasCheckFunc; llvm::Function* m_gasCheckFunc;
}; };

17
evmcc/Runtime.cpp

@ -1,12 +1,27 @@
#include "Runtime.h" #include "Runtime.h"
#include <libevm/VM.h>
#include "Type.h"
namespace evmcc namespace evmcc
{ {
static Runtime* g_runtime; static Runtime* g_runtime;
extern "C" { EXPORT i256 gas; } extern "C"
{
EXPORT i256 gas;
EXPORT void rt_exit(int32_t _returnCode)
{
auto returnCode = static_cast<ReturnCode>(_returnCode);
if (returnCode == ReturnCode::OutOfGas)
BOOST_THROW_EXCEPTION(dev::eth::OutOfGas());
}
}
Runtime::Runtime(dev::u256 _gas, std::unique_ptr<dev::eth::ExtVMFace> _ext): Runtime::Runtime(dev::u256 _gas, std::unique_ptr<dev::eth::ExtVMFace> _ext):
m_ext(std::move(_ext)) m_ext(std::move(_ext))

1
evmcc/Type.h

@ -34,6 +34,7 @@ enum class ReturnCode
Suicide = 2, Suicide = 2,
BadJumpDestination = 101, BadJumpDestination = 101,
OutOfGas = 102,
}; };
struct Constant struct Constant

Loading…
Cancel
Save