From f1a1fe22a6026fd07e4ff6b8a7fa62412f8ec4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 6 Mar 2015 18:29:17 +0100 Subject: [PATCH] Update gas costs for PoC-9 (WIP) --- evmjit/libevmjit/GasMeter.cpp | 157 ++++++++++++++++++++++++---------- evmjit/libevmjit/Memory.cpp | 6 +- 2 files changed, 116 insertions(+), 47 deletions(-) diff --git a/evmjit/libevmjit/GasMeter.cpp b/evmjit/libevmjit/GasMeter.cpp index 5b748650d..129b60e8a 100644 --- a/evmjit/libevmjit/GasMeter.cpp +++ b/evmjit/libevmjit/GasMeter.cpp @@ -17,52 +17,112 @@ namespace jit namespace // Helper functions { -int64_t const c_stepGas = 1; -int64_t const c_balanceGas = 20; -int64_t const c_sha3Gas = 10; -int64_t const c_sha3WordGas = 10; -int64_t const c_sloadGas = 20; -int64_t const c_sstoreSetGas = 300; -int64_t const c_sstoreResetGas = 100; -int64_t const c_sstoreRefundGas = 100; -int64_t const c_createGas = 100; -int64_t const c_createDataGas = 5; -int64_t const c_callGas = 20; -int64_t const c_expGas = 1; -int64_t const c_expByteGas = 1; -int64_t const c_memoryGas = 1; -int64_t const c_txDataZeroGas = 1; -int64_t const c_txDataNonZeroGas = 5; -int64_t const c_txGas = 500; -int64_t const c_logGas = 32; -int64_t const c_logDataGas = 1; -int64_t const c_logTopicGas = 32; -int64_t const c_copyGas = 1; +int64_t const c_stepGas[] = {0, 2, 3, 5, 8, 10, 20}; +int64_t const c_expByteGas = 10; +int64_t const c_sha3Gas = 30; +int64_t const c_sha3WordGas = 6; +int64_t const c_sloadGas = 50; +int64_t const c_sstoreSetGas = 20000; +int64_t const c_sstoreResetGas = 5000; +int64_t const c_jumpdestGas = 1; +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_memoryGas = 3; +int64_t const c_copyGas = 3; int64_t getStepCost(Instruction inst) { switch (inst) { - default: // Assumes instruction code is valid - return c_stepGas; - + // Tier 0 case Instruction::STOP: + case Instruction::RETURN: case Instruction::SUICIDE: case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore() - return 0; - - case Instruction::EXP: return c_expGas; - - case Instruction::SLOAD: return c_sloadGas; - - case Instruction::SHA3: return c_sha3Gas; - - case Instruction::BALANCE: return c_balanceGas; - - case Instruction::CALL: - case Instruction::CALLCODE: return c_callGas; - - case Instruction::CREATE: return c_createGas; + return c_stepGas[0]; + + // Tier 1 + case Instruction::ADDRESS: + case Instruction::ORIGIN: + case Instruction::CALLER: + case Instruction::CALLVALUE: + case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::GASPRICE: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: + case Instruction::POP: + case Instruction::PC: + case Instruction::MSIZE: + case Instruction::GAS: + return c_stepGas[1]; + + // Tier 2 + case Instruction::ADD: + case Instruction::SUB: + case Instruction::LT: + case Instruction::GT: + case Instruction::SLT: + case Instruction::SGT: + case Instruction::EQ: + case Instruction::ISZERO: + case Instruction::AND: + case Instruction::OR: + case Instruction::XOR: + case Instruction::NOT: + case Instruction::BYTE: + case Instruction::CALLDATALOAD: + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::MLOAD: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::ANY_PUSH: + case Instruction::ANY_DUP: + case Instruction::ANY_SWAP: + return c_stepGas[2]; + + // Tier 3 + case Instruction::MUL: + case Instruction::DIV: + case Instruction::SDIV: + case Instruction::MOD: + case Instruction::SMOD: + case Instruction::SIGNEXTEND: + return c_stepGas[3]; + + // Tier 4 + case Instruction::ADDMOD: + case Instruction::MULMOD: + case Instruction::JUMP: + return c_stepGas[4]; + + // Tier 5 + case Instruction::EXP: + case Instruction::JUMPI: + return c_stepGas[5]; + + // Tier 6 + case Instruction::BALANCE: + case Instruction::EXTCODESIZE: + case Instruction::EXTCODECOPY: + case Instruction::BLOCKHASH: + return c_stepGas[6]; + + case Instruction::SHA3: + return c_sha3Gas; + + case Instruction::SLOAD: + return c_sloadGas; + + case Instruction::JUMPDEST: + return c_jumpdestGas; case Instruction::LOG0: case Instruction::LOG1: @@ -73,7 +133,16 @@ int64_t getStepCost(Instruction inst) auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); return c_logGas + numTopics * c_logTopicGas; } + + case Instruction::CALL: + case Instruction::CALLCODE: + return c_callGas; + + case Instruction::CREATE: + return c_createGas; } + + return 0; // TODO: Add UNREACHABLE macro } } @@ -152,7 +221,7 @@ void GasMeter::countExp(llvm::Value* _exponent) auto lz = m_builder.CreateTrunc(lz256, Type::Gas, "lz"); auto sigBits = m_builder.CreateSub(m_builder.getInt64(256), lz, "sigBits"); auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, m_builder.getInt64(7)), m_builder.getInt64(8)); - count(sigBytes); + count(m_builder.CreateNUWMul(sigBytes, m_builder.getInt64(c_expByteGas))); } void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValue) @@ -173,8 +242,8 @@ void GasMeter::countLogData(llvm::Value* _dataLength) { assert(m_checkCall); assert(m_blockCost > 0); // LOGn instruction is already counted - static_assert(c_logDataGas == 1, "Log data gas cost has changed. Update GasMeter."); - count(_dataLength); + static_assert(c_logDataGas != 1, "Log data gas cost has changed. Update GasMeter."); + count(m_builder.CreateNUWMul(_dataLength, Constant::get(c_logDataGas))); // TODO: Use i64 } void GasMeter::countSha3Data(llvm::Value* _dataLength) @@ -217,14 +286,14 @@ void GasMeter::commitCostBlock() void GasMeter::countMemory(llvm::Value* _additionalMemoryInWords, llvm::Value* _jmpBuf, llvm::Value* _gasPtr) { - static_assert(c_memoryGas == 1, "Memory gas cost has changed. Update GasMeter."); + static_assert(c_memoryGas != 1, "Memory gas cost has changed. Update GasMeter."); count(_additionalMemoryInWords, _jmpBuf, _gasPtr); } void GasMeter::countCopy(llvm::Value* _copyWords) { - static_assert(c_copyGas == 1, "Copy gas cost has changed. Update GasMeter."); - count(_copyWords); + static_assert(c_copyGas != 1, "Copy gas cost has changed. Update GasMeter."); + count(m_builder.CreateNUWMul(_copyWords, m_builder.getInt64(c_copyGas))); } } diff --git a/evmjit/libevmjit/Memory.cpp b/evmjit/libevmjit/Memory.cpp index 515121e31..27afab62c 100644 --- a/evmjit/libevmjit/Memory.cpp +++ b/evmjit/libevmjit/Memory.cpp @@ -74,14 +74,14 @@ llvm::Function* Memory::getRequireFunc() // Check gas first auto w1 = m_builder.CreateLShr(sizeReq, 5); auto w1s = m_builder.CreateNUWMul(w1, w1); - auto c1 = m_builder.CreateAdd(w1, m_builder.CreateLShr(w1s, 10)); + auto c1 = m_builder.CreateAdd(m_builder.CreateNUWMul(w1, m_builder.getInt64(3)), m_builder.CreateLShr(w1s, 9)); auto w0 = m_builder.CreateLShr(sizeCur, 5); auto w0s = m_builder.CreateNUWMul(w0, w0); - auto c0 = m_builder.CreateAdd(w0, m_builder.CreateLShr(w0s, 10)); + auto c0 = m_builder.CreateAdd(m_builder.CreateNUWMul(w0, m_builder.getInt64(3)), m_builder.CreateLShr(w0s, 9)); auto cc = m_builder.CreateNUWSub(c1, c0); auto costOk = m_builder.CreateAnd(blkOffsetOk, blkSizeOk, "costOk"); auto c = m_builder.CreateSelect(costOk, cc, m_builder.getInt64(std::numeric_limits::max()), "c"); - m_gasMeter.countMemory(c, jmpBuf, gas); + m_gasMeter.count(c, jmpBuf, gas); // Resize m_memory.extend(mem, sizeReq); m_builder.CreateBr(returnBB);