From 4954ae2cda6fa39d0664f9e061adc3e1d92249bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 9 Mar 2015 14:51:18 +0100 Subject: [PATCH] Update gas costs for PoC-9: changes in CALL gas price support --- libevmjit-cpp/Env.cpp | 31 +++++++++++++++++++++++++------ libevmjit/Compiler.cpp | 11 +++-------- libevmjit/Ext.cpp | 10 +++++++--- libevmjit/Ext.h | 2 +- libevmjit/GasMeter.cpp | 2 +- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/libevmjit-cpp/Env.cpp b/libevmjit-cpp/Env.cpp index 874993c84..39007c59d 100644 --- a/libevmjit-cpp/Env.cpp +++ b/libevmjit-cpp/Env.cpp @@ -62,19 +62,38 @@ extern "C" *o_address = {}; } - EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress) + EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress) { auto value = llvm2eth(*_value); + auto receiveAddress = right160(*_receiveAddress); + auto codeAddress = right160(*_codeAddress); + const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL + + *io_gas -= _callGas; + if (*io_gas < 0) + return false; + + if (isCall && !_env->exists(receiveAddress)) + *io_gas -= static_cast(c_callNewAccountGas); // no underflow, *io_gas non-negative before + + if (value > 0) // value transfer + { + assert(c_callValueTransferGas > c_callStipend && "Overflow possible"); + *io_gas -= static_cast(c_callValueTransferGas); // no underflow + _callGas += static_cast(c_callStipend); // overflow possibility, but in the same time *io_gas < 0 + } + + if (*io_gas < 0) + return false; + if (_env->balance(_env->myAddress) >= value && _env->depth < 1024) { _env->subBalance(value); - auto receiveAddress = right160(*_receiveAddress); auto inRef = bytesConstRef{_inBeg, _inSize}; auto outRef = bytesRef{_outBeg, _outSize}; - auto codeAddress = right160(*_codeAddress); - u256 gas = *io_gas; - auto ret = _env->call(receiveAddress, value, inRef, gas, outRef, {}, {}, codeAddress); - *io_gas = static_cast(gas); + u256 callGas = _callGas; + auto ret = _env->call(receiveAddress, value, inRef, callGas, outRef, {}, {}, codeAddress); + *io_gas += static_cast(callGas); // It is never more than initial _callGas return ret; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 6fa82c870..22837f176 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -755,7 +755,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::CALL: case Instruction::CALLCODE: { - auto callGas256 = stack.pop(); + auto callGas = stack.pop(); auto codeAddress = stack.pop(); auto value = stack.pop(); auto inOff = stack.pop(); @@ -773,13 +773,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti if (inst == Instruction::CALLCODE) receiveAddress = _runtimeManager.get(RuntimeData::Address); - auto gas = _runtimeManager.getGas(); - _gasMeter.count(callGas256); - auto callGas = m_builder.CreateTrunc(callGas256, Type::Gas); - auto gasLeft = m_builder.CreateNSWSub(gas, callGas); - _runtimeManager.setGas(callGas); - auto ret = _ext.call(receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); - _gasMeter.giveBack(gasLeft); + auto ret = _ext.call(callGas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); + _gasMeter.count(m_builder.getInt64(0), _runtimeManager.getJmpBuf(), _runtimeManager.getGasPtr()); stack.push(ret); break; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 38deef214..d35aebc68 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -41,7 +41,7 @@ std::array::value> const& getEnvFuncDescs() FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})}, FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::GasPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})}, - FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::GasPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})}, + FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::GasPtr, Type::Gas, 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_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, @@ -136,7 +136,7 @@ llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::V return address; } -llvm::Value* Ext::call(llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) +llvm::Value* Ext::call(llvm::Value* _callGas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) { auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress); auto inBeg = m_memoryMan.getBytePtr(_inOff); @@ -144,7 +144,11 @@ llvm::Value* Ext::call(llvm::Value* _receiveAddress, llvm::Value* _value, llvm:: auto outBeg = m_memoryMan.getBytePtr(_outOff); auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size"); auto codeAddress = Endianness::toBE(m_builder, _codeAddress); - auto ret = createCall(EnvFunc::call, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), byPtr(receiveAddress), byPtr(_value), inBeg, inSize, outBeg, outSize, byPtr(codeAddress)}); + auto callGas = m_builder.CreateSelect( + m_builder.CreateICmpULE(_callGas, m_builder.CreateZExt(Constant::gasMax, Type::Word)), + m_builder.CreateTrunc(_callGas, Type::Gas), + Constant::gasMax); + auto ret = createCall(EnvFunc::call, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), callGas, byPtr(receiveAddress), byPtr(_value), inBeg, inSize, outBeg, outSize, byPtr(codeAddress)}); return m_builder.CreateZExt(ret, Type::Word, "ret"); } diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 1c0c0fc56..b0048d2e9 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -51,7 +51,7 @@ public: llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); - llvm::Value* call(llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress); + llvm::Value* call(llvm::Value* _callGas, 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); diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 129b60e8a..6a29235fb 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -29,7 +29,7 @@ int64_t const c_logGas = 375; int64_t const c_logTopicGas = 375; int64_t const c_logDataGas = 8; int64_t const c_callGas = 40; -int64_t const c_createGas = 23000; +int64_t const c_createGas = 32000; int64_t const c_memoryGas = 3; int64_t const c_copyGas = 3;