diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 6c6c00ff7..3a0d8d034 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -504,6 +504,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode auto inOff = stack.pop(); auto inSize = stack.pop(); _memory.require(inOff, inSize); + _gasMeter.countSha3Data(inSize); auto hash = _ext.sha3(inOff, inSize); stack.push(hash); break; diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 0f67045a3..3eb16899a 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -21,12 +21,14 @@ namespace // Helper functions uint64_t const c_stepGas = 1; uint64_t const c_balanceGas = 20; -uint64_t const c_sha3Gas = 20; +uint64_t const c_sha3Gas = 10; +uint64_t const c_sha3WordGas = 10; uint64_t const c_sloadGas = 20; uint64_t const c_sstoreSetGas = 300; uint64_t const c_sstoreResetGas = 100; uint64_t const c_sstoreRefundGas = 100; uint64_t const c_createGas = 100; +uint64_t const c_createDataGas = 5; uint64_t const c_callGas = 20; uint64_t const c_expGas = 1; uint64_t const c_expByteGas = 1; @@ -44,7 +46,7 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure switch (inst) { default: // Assumes instruction code is valid - return 1; + return c_stepGas; case Instruction::STOP: case Instruction::SUICIDE: @@ -190,6 +192,19 @@ void GasMeter::countLogData(llvm::Value* _dataLength) commitCostBlock(_dataLength); // TODO: commit is not necessary } +void GasMeter::countSha3Data(llvm::Value* _dataLength) +{ + assert(m_checkCall); + assert(m_blockCost > 0); // SHA3 instruction is already counted + + // TODO: This round ups to 32 happens in many places + // FIXME: Overflow possible but Memory::require() also called. Probably 64-bit arith can be used. + static_assert(c_sha3WordGas != 1, "SHA3 data cost has changed. Update GasMeter"); + auto words = m_builder.CreateUDiv(m_builder.CreateAdd(_dataLength, Constant::get(31)), Constant::get(32)); + auto cost = m_builder.CreateNUWMul(Constant::get(c_sha3WordGas), words); + count(cost); +} + void GasMeter::giveBack(llvm::Value* _gas) { m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas)); diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 2d8fb3044..890791ff1 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -32,6 +32,9 @@ public: /// Count gas cost of LOG data void countLogData(llvm::Value* _dataLength); + /// Count gas cost of SHA3 data + void countSha3Data(llvm::Value* _dataLength); + /// Finalize cost-block by checking gas needed for the block before the block /// @param _additionalCost adds additional cost to cost-block before commit void commitCostBlock(llvm::Value* _additionalCost = nullptr);