Browse Source

Update gas costs for PoC-9: changes in CALL gas price support

cl-refactor
Paweł Bylica 10 years ago
parent
commit
4954ae2cda
  1. 31
      libevmjit-cpp/Env.cpp
  2. 11
      libevmjit/Compiler.cpp
  3. 10
      libevmjit/Ext.cpp
  4. 2
      libevmjit/Ext.h
  5. 2
      libevmjit/GasMeter.cpp

31
libevmjit-cpp/Env.cpp

@ -62,19 +62,38 @@ extern "C"
*o_address = {}; *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 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<int64_t>(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<int64_t>(c_callValueTransferGas); // no underflow
_callGas += static_cast<int64_t>(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) if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
{ {
_env->subBalance(value); _env->subBalance(value);
auto receiveAddress = right160(*_receiveAddress);
auto inRef = bytesConstRef{_inBeg, _inSize}; auto inRef = bytesConstRef{_inBeg, _inSize};
auto outRef = bytesRef{_outBeg, _outSize}; auto outRef = bytesRef{_outBeg, _outSize};
auto codeAddress = right160(*_codeAddress); u256 callGas = _callGas;
u256 gas = *io_gas; auto ret = _env->call(receiveAddress, value, inRef, callGas, outRef, {}, {}, codeAddress);
auto ret = _env->call(receiveAddress, value, inRef, gas, outRef, {}, {}, codeAddress); *io_gas += static_cast<int64_t>(callGas); // It is never more than initial _callGas
*io_gas = static_cast<int64_t>(gas);
return ret; return ret;
} }

11
libevmjit/Compiler.cpp

@ -755,7 +755,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
{ {
auto callGas256 = stack.pop(); auto callGas = stack.pop();
auto codeAddress = stack.pop(); auto codeAddress = stack.pop();
auto value = stack.pop(); auto value = stack.pop();
auto inOff = stack.pop(); auto inOff = stack.pop();
@ -773,13 +773,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
if (inst == Instruction::CALLCODE) if (inst == Instruction::CALLCODE)
receiveAddress = _runtimeManager.get(RuntimeData::Address); receiveAddress = _runtimeManager.get(RuntimeData::Address);
auto gas = _runtimeManager.getGas(); auto ret = _ext.call(callGas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress);
_gasMeter.count(callGas256); _gasMeter.count(m_builder.getInt64(0), _runtimeManager.getJmpBuf(), _runtimeManager.getGasPtr());
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);
stack.push(ret); stack.push(ret);
break; break;
} }

10
libevmjit/Ext.cpp

@ -41,7 +41,7 @@ std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})}, 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_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_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_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_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})}, 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; 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 receiveAddress = Endianness::toBE(m_builder, _receiveAddress);
auto inBeg = m_memoryMan.getBytePtr(_inOff); 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 outBeg = m_memoryMan.getBytePtr(_outOff);
auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size"); auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size");
auto codeAddress = Endianness::toBE(m_builder, _codeAddress); 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"); return m_builder.CreateZExt(ret, Type::Word, "ret");
} }

2
libevmjit/Ext.h

@ -51,7 +51,7 @@ public:
llvm::Value* balance(llvm::Value* _address); llvm::Value* balance(llvm::Value* _address);
llvm::Value* calldataload(llvm::Value* _index); llvm::Value* calldataload(llvm::Value* _index);
llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); 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* blockhash(llvm::Value* _number);
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);

2
libevmjit/GasMeter.cpp

@ -29,7 +29,7 @@ int64_t const c_logGas = 375;
int64_t const c_logTopicGas = 375; int64_t const c_logTopicGas = 375;
int64_t const c_logDataGas = 8; int64_t const c_logDataGas = 8;
int64_t const c_callGas = 40; 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_memoryGas = 3;
int64_t const c_copyGas = 3; int64_t const c_copyGas = 3;

Loading…
Cancel
Save