diff --git a/libevm/FeeStructure.cpp b/libevm/FeeStructure.cpp index b9974a3e7..661f7af6f 100644 --- a/libevm/FeeStructure.cpp +++ b/libevm/FeeStructure.cpp @@ -21,3 +21,159 @@ */ #include "FeeStructure.h" + +#include + +namespace dev +{ +namespace eth +{ + +uint32_t FeeStructure::getInstructionFee(Instruction _inst) BOOST_NOEXCEPT_OR_NOTHROW +{ + switch (_inst) + { + case Instruction::STOP: + case Instruction::SUICIDE: + default: // In case of bad instruction return 0 + return 0; + + case Instruction::SSTORE: + return c_sstoreGas; + + case Instruction::SLOAD: + return c_sloadGas; + + case Instruction::SHA3: + return c_sha3Gas; + + case Instruction::BALANCE: + return c_sha3Gas; + + case Instruction::CALL: + case Instruction::CALLCODE: + return c_callGas; + + case Instruction::CREATE: + return c_createGas; + + case Instruction::ADD: + case Instruction::MUL: + case Instruction::SUB: + case Instruction::DIV: + case Instruction::SDIV: + case Instruction::MOD: + case Instruction::SMOD: + case Instruction::EXP: + case Instruction::NEG: + case Instruction::LT: + case Instruction::GT: + case Instruction::SLT: + case Instruction::SGT: + case Instruction::EQ: + case Instruction::NOT: + case Instruction::AND: + case Instruction::OR: + case Instruction::XOR: + case Instruction::BYTE: + case Instruction::ADDMOD: + case Instruction::MULMOD: + case Instruction::ADDRESS: + case Instruction::ORIGIN: + case Instruction::CALLER: + case Instruction::CALLVALUE: + case Instruction::CALLDATALOAD: + case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::EXTCODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + case Instruction::POP: + case Instruction::DUP1: + case Instruction::DUP2: + case Instruction::DUP3: + case Instruction::DUP4: + case Instruction::DUP5: + case Instruction::DUP6: + case Instruction::DUP7: + case Instruction::DUP8: + case Instruction::DUP9: + case Instruction::DUP10: + case Instruction::DUP11: + case Instruction::DUP12: + case Instruction::DUP13: + case Instruction::DUP14: + case Instruction::DUP15: + case Instruction::DUP16: + case Instruction::SWAP1: + case Instruction::SWAP2: + case Instruction::SWAP3: + case Instruction::SWAP4: + case Instruction::SWAP5: + case Instruction::SWAP6: + case Instruction::SWAP7: + case Instruction::SWAP8: + case Instruction::SWAP9: + case Instruction::SWAP10: + case Instruction::SWAP11: + case Instruction::SWAP12: + case Instruction::SWAP13: + case Instruction::SWAP14: + case Instruction::SWAP15: + case Instruction::SWAP16: + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::PC: + case Instruction::MSIZE: + case Instruction::GAS: + case Instruction::JUMPDEST: + case Instruction::RETURN: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::MLOAD: + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::EXTCODECOPY: + return c_stepGas; + } +} + +} +} \ No newline at end of file diff --git a/libevm/FeeStructure.h b/libevm/FeeStructure.h index 574021d95..73ea48156 100644 --- a/libevm/FeeStructure.h +++ b/libevm/FeeStructure.h @@ -22,6 +22,8 @@ #pragma once +#include + namespace dev { namespace eth @@ -31,18 +33,20 @@ enum class Instruction: uint8_t; struct FeeStructure { - static uint32_t const c_stepGas = 1; ///< Once per operation, except for SSTORE, SLOAD, BALANCE, SHA3, CREATE, CALL. - static uint32_t const c_balanceGas = 20; ///< Once per BALANCE operation. - static uint32_t const c_sha3Gas = 20; ///< Once per SHA3 operation. - static uint32_t const c_sloadGas = 20; ///< Once per SLOAD operation. - static uint32_t const c_sstoreGas = 100; ///< Once per non-zero storage element in a CREATE call/transaction. Also, once/twice per SSTORE operation depending on whether the zeroness changes (twice iff it changes from zero; nothing at all if to zero) or doesn't (once). - static uint32_t const c_createGas = 100; ///< Once per CREATE operation & contract-creation transaction. - static uint32_t const c_callGas = 20; ///< Once per CALL operation & message call transaction. - static uint32_t const c_memoryGas = 1; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. - static uint32_t const c_txDataGas = 5; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions. - static uint32_t const c_txGas = 500; ///< Per transaction. NOTE: Not payable on data of calls between transactions. - - static uint32_t getInstructionFee(Instruction _inst); + static uint32_t const c_stepGas = 1; ///< Once per operation, except for SSTORE, SLOAD, BALANCE, SHA3, CREATE, CALL. + static uint32_t const c_balanceGas = 20; ///< Once per BALANCE operation. + static uint32_t const c_sha3Gas = 20; ///< Once per SHA3 operation. + static uint32_t const c_sloadGas = 20; ///< Once per SLOAD operation. + static uint32_t const c_sstoreGas = 100; ///< Once per non-zero storage element in a CREATE call/transaction. Also, once/twice per SSTORE operation depending on whether the zeroness changes (twice iff it changes from zero; nothing at all if to zero) or doesn't (once). + static uint32_t const c_createGas = 100; ///< Once per CREATE operation & contract-creation transaction. + static uint32_t const c_callGas = 20; ///< Once per CALL operation & message call transaction. + static uint32_t const c_memoryGas = 1; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + static uint32_t const c_txDataGas = 5; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions. + static uint32_t const c_txGas = 500; ///< Per transaction. NOTE: Not payable on data of calls between transactions. + + /// Returns step fee of the instruction. + /// In case of bad instruction code, returns 0. + static uint32_t getInstructionFee(Instruction _inst) BOOST_NOEXCEPT_OR_NOTHROW; }; } diff --git a/libevm/VM.h b/libevm/VM.h index 6eb57941d..7c1e66ed5 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -101,17 +101,10 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con Instruction inst = (Instruction)_ext.getCode(m_curPC); // FEES... - bigint runGas = FeeStructure::c_stepGas; + bigint runGas = FeeStructure::getInstructionFee(inst); bigint newTempSize = m_temp.size(); switch (inst) { - case Instruction::STOP: - runGas = 0; - break; - - case Instruction::SUICIDE: - runGas = 0; - break; case Instruction::SSTORE: require(2); @@ -119,12 +112,6 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con runGas = FeeStructure::c_sstoreGas * 2; else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2]) runGas = 0; - else - runGas = FeeStructure::c_sstoreGas; - break; - - case Instruction::SLOAD: - runGas = FeeStructure::c_sloadGas; break; // These all operate on memory and therefore potentially expand it: @@ -146,7 +133,6 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::SHA3: require(2); - runGas = FeeStructure::c_sha3Gas; newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); break; case Instruction::CALLDATACOPY: @@ -161,20 +147,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con require(4); newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); break; - - case Instruction::BALANCE: - runGas = FeeStructure::c_balanceGas; - break; case Instruction::CALL: - require(7); - runGas = FeeStructure::c_callGas + m_stack[m_stack.size() - 1]; - newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); - break; - case Instruction::CALLCODE: require(7); - runGas = FeeStructure::c_callGas + m_stack[m_stack.size() - 1]; + runGas += m_stack[m_stack.size() - 1]; newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); break; @@ -184,120 +161,9 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con auto inOff = m_stack[m_stack.size() - 2]; auto inSize = m_stack[m_stack.size() - 3]; newTempSize = inOff + inSize; - runGas = FeeStructure::c_createGas; break; } - case Instruction::ADD: - case Instruction::MUL: - case Instruction::SUB: - case Instruction::DIV: - case Instruction::SDIV: - case Instruction::MOD: - case Instruction::SMOD: - case Instruction::EXP: - case Instruction::NEG: - case Instruction::LT: - case Instruction::GT: - case Instruction::SLT: - case Instruction::SGT: - case Instruction::EQ: - case Instruction::NOT: - case Instruction::AND: - case Instruction::OR: - case Instruction::XOR: - case Instruction::BYTE: - case Instruction::ADDMOD: - case Instruction::MULMOD: - case Instruction::ADDRESS: - case Instruction::ORIGIN: - case Instruction::CALLER: - case Instruction::CALLVALUE: - case Instruction::CALLDATALOAD: - case Instruction::CALLDATASIZE: - case Instruction::CODESIZE: - case Instruction::EXTCODESIZE: - case Instruction::GASPRICE: - case Instruction::PREVHASH: - case Instruction::COINBASE: - case Instruction::TIMESTAMP: - case Instruction::NUMBER: - case Instruction::DIFFICULTY: - case Instruction::GASLIMIT: - case Instruction::PUSH1: - case Instruction::PUSH2: - case Instruction::PUSH3: - case Instruction::PUSH4: - case Instruction::PUSH5: - case Instruction::PUSH6: - case Instruction::PUSH7: - case Instruction::PUSH8: - case Instruction::PUSH9: - case Instruction::PUSH10: - case Instruction::PUSH11: - case Instruction::PUSH12: - case Instruction::PUSH13: - case Instruction::PUSH14: - case Instruction::PUSH15: - case Instruction::PUSH16: - case Instruction::PUSH17: - case Instruction::PUSH18: - case Instruction::PUSH19: - case Instruction::PUSH20: - case Instruction::PUSH21: - case Instruction::PUSH22: - case Instruction::PUSH23: - case Instruction::PUSH24: - case Instruction::PUSH25: - case Instruction::PUSH26: - case Instruction::PUSH27: - case Instruction::PUSH28: - case Instruction::PUSH29: - case Instruction::PUSH30: - case Instruction::PUSH31: - case Instruction::PUSH32: - case Instruction::POP: - case Instruction::DUP1: - case Instruction::DUP2: - case Instruction::DUP3: - case Instruction::DUP4: - case Instruction::DUP5: - case Instruction::DUP6: - case Instruction::DUP7: - case Instruction::DUP8: - case Instruction::DUP9: - case Instruction::DUP10: - case Instruction::DUP11: - case Instruction::DUP12: - case Instruction::DUP13: - case Instruction::DUP14: - case Instruction::DUP15: - case Instruction::DUP16: - case Instruction::SWAP1: - case Instruction::SWAP2: - case Instruction::SWAP3: - case Instruction::SWAP4: - case Instruction::SWAP5: - case Instruction::SWAP6: - case Instruction::SWAP7: - case Instruction::SWAP8: - case Instruction::SWAP9: - case Instruction::SWAP10: - case Instruction::SWAP11: - case Instruction::SWAP12: - case Instruction::SWAP13: - case Instruction::SWAP14: - case Instruction::SWAP15: - case Instruction::SWAP16: - case Instruction::JUMP: - case Instruction::JUMPI: - case Instruction::PC: - case Instruction::MSIZE: - case Instruction::GAS: - case Instruction::JUMPDEST: - break; - default: - BOOST_THROW_EXCEPTION(BadInstruction()); } newTempSize = (newTempSize + 31) / 32 * 32;