Browse Source

New gas pricing for PoC-9.

cl-refactor
Gav Wood 10 years ago
parent
commit
e3219c6563
  1. 3
      libethereum/ExtVM.h
  2. 3
      libevm/ExtVMFace.h
  3. 59
      libevm/FeeStructure.cpp
  4. 50
      libevm/FeeStructure.h
  5. 197
      libevm/VM.cpp
  6. 267
      libevmcore/Instruction.cpp
  7. 14
      libevmcore/Instruction.h

3
libethereum/ExtVM.h

@ -69,6 +69,9 @@ public:
/// Determine account's TX count. /// Determine account's TX count.
virtual u256 txCount(Address _a) override final { return m_s.transactionsFrom(_a); } virtual u256 txCount(Address _a) override final { return m_s.transactionsFrom(_a); }
/// Does the account exist?
virtual bool exists(Address _a) { return m_s.addressInUse(_a); }
/// Suicide the associated contract to the given address. /// Suicide the associated contract to the given address.
virtual void suicide(Address _a) override final virtual void suicide(Address _a) override final
{ {

3
libevm/ExtVMFace.h

@ -142,6 +142,9 @@ public:
/// Determine account's TX count. /// Determine account's TX count.
virtual u256 txCount(Address) { return 0; } virtual u256 txCount(Address) { return 0; }
/// Does the account exist?
virtual bool exists(Address) { return false; }
/// Suicide the associated contract and give proceeds to the given address. /// Suicide the associated contract and give proceeds to the given address.
virtual void suicide(Address) { sub.suicides.insert(myAddress); } virtual void suicide(Address) { sub.suicides.insert(myAddress); }

59
libevm/FeeStructure.cpp

@ -25,24 +25,41 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
u256 const dev::eth::c_stepGas = 1; u256 const dev::eth::c_tierStepGas[8] = { 0, 2, 3, 5, 8, 10, 20, 0 };
u256 const dev::eth::c_balanceGas = 20; u256 const dev::eth::c_expGas = 10;
u256 const dev::eth::c_sha3Gas = 10; u256 const dev::eth::c_expByteGas = 10;
u256 const dev::eth::c_sha3WordGas = 10;
u256 const dev::eth::c_sloadGas = 20; u256 const dev::eth::c_sha3Gas = 30;
u256 const dev::eth::c_sstoreSetGas = 300; u256 const dev::eth::c_sha3WordGas = 6;
u256 const dev::eth::c_sstoreResetGas = 100;
u256 const dev::eth::c_sstoreRefundGas = 100; u256 const dev::eth::c_sloadGas = 50;
u256 const dev::eth::c_createGas = 100; u256 const dev::eth::c_sstoreSetGas = 20000;
u256 const dev::eth::c_createDataGas = 5; u256 const dev::eth::c_sstoreResetGas = 5000;
u256 const dev::eth::c_callGas = 20; u256 const dev::eth::c_sstoreClearGas = 5000;
u256 const dev::eth::c_expGas = 1; u256 const dev::eth::c_sstoreRefundGas = 15000;
u256 const dev::eth::c_expByteGas = 1; u256 const dev::eth::c_jumpdestGas = 1;
u256 const dev::eth::c_memoryGas = 1;
u256 const dev::eth::c_txDataZeroGas = 1; u256 const dev::eth::c_logGas = 2000;
u256 const dev::eth::c_txDataNonZeroGas = 5; u256 const dev::eth::c_logDataGas = 8;
u256 const dev::eth::c_txGas = 500; u256 const dev::eth::c_logTopicGas = 2000;
u256 const dev::eth::c_logGas = 32;
u256 const dev::eth::c_logDataGas = 1; u256 const dev::eth::c_createGas = 32000;
u256 const dev::eth::c_logTopicGas = 32;
u256 const dev::eth::c_copyGas = 1; u256 const dev::eth::c_callGas = 40;
u256 const dev::eth::c_callValueTransferGas = 6700;
u256 const dev::eth::c_callNewAccountGas = 25000;
u256 const dev::eth::c_suicideRefundGas = 24000;
u256 const dev::eth::c_memoryGas = 3;
u256 const dev::eth::c_quadCoeffDiv = 512;
u256 const dev::eth::c_createDataGas = 200;
u256 const dev::eth::c_txGas = 21000;
u256 const dev::eth::c_txDataZeroGas = 37;
u256 const dev::eth::c_txDataNonZeroGas = 2;
u256 const dev::eth::c_copyGas = 3;

50
libevm/FeeStructure.h

@ -28,27 +28,37 @@ namespace dev
namespace eth namespace eth
{ {
extern u256 const c_stepGas; ///< Once per operation, except for SSTORE, SLOAD, BALANCE, SHA3, CREATE, CALL. extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them.
extern u256 const c_balanceGas; ///< Once per BALANCE operation. extern u256 const c_expGas; ///< Once per EXP instuction.
extern u256 const c_sha3Gas; ///< Once per SHA3 operation. extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction.
extern u256 const c_sha3WordGas;
extern u256 const c_sloadGas; ///< Once per SLOAD operation. extern u256 const c_sha3Gas; ///< Once per SHA3 operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero. extern u256 const c_sha3WordGas; ///< Once per word of the SHA3 operation's data.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness doesn't change.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero. extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_sloadGas; ///< Once per SLOAD operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness doesn't change.
extern u256 const c_sstoreClearGas; ///< Once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_jumpdestGas; ///< Once per JUMPDEST operation.
extern u256 const c_logGas; ///< Per LOG* operation.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_createDataGas; extern u256 const c_createDataGas;
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction. extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_expGas; ///< Once per EXP instuction. extern u256 const c_callNewAccountGas; ///< Paid for CALL when the destination address didn't exist prior.
extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction. extern u256 const c_callValueTransferGas; ///< Paid for CALL when the value transfor is non-zero.
extern u256 const c_memoryGas; ///< 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. extern u256 const c_suicideRefundGas; ///< Refunded following a suicide operation.
extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. extern u256 const c_memoryGas; ///< 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.
extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions. extern u256 const c_quadCoeffDiv; ///< Divisor for the quadratic particle of the memory cost equation.
extern u256 const c_logGas; ///< Per LOG* operation. extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data. extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
} }
} }

197
libevm/VM.cpp

@ -21,7 +21,7 @@
#include "VM.h" #include "VM.h"
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -32,13 +32,33 @@ void VM::reset(u256 _gas) noexcept
m_jumpDests.clear(); m_jumpDests.clear();
} }
struct InstructionMetric
{
int gasPriceTier;
int args;
};
static array<InstructionMetric, 256> metrics()
{
array<InstructionMetric, 256> s_ret;
for (unsigned i = 0; i < 256; ++i)
{
InstructionInfo inst = instructionInfo((Instruction)i);
s_ret[i].gasPriceTier = inst.gasPriceTier;
s_ret[i].args = inst.args;
}
return s_ret;
}
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{ {
static const array<InstructionMetric, 256> c_metrics = metrics();
auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
auto gasForMem = [](bigint _size) -> bigint auto gasForMem = [](bigint _size) -> bigint
{ {
bigint s = _size / 32; bigint s = _size / 32;
return (bigint)c_memoryGas * (s + s * s / 1024); return (bigint)c_memoryGas * s + s * s / c_quadCoeffDiv;
}; };
if (m_jumpDests.empty()) if (m_jumpDests.empty())
@ -57,36 +77,35 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
Instruction inst = (Instruction)_ext.getCode(m_curPC); Instruction inst = (Instruction)_ext.getCode(m_curPC);
// FEES... // FEES...
bigint runGas = c_stepGas; bigint runGas;
bigint newTempSize = m_temp.size(); bigint newTempSize = m_temp.size();
bigint copySize = 0; bigint copySize = 0;
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
auto metric = c_metrics[(int)inst];
int gasPriceTier = metric.gasPriceTier;
if (gasPriceTier == InvalidTier)
BOOST_THROW_EXCEPTION(BadInstruction());
else
runGas = c_tierStepGas[metric.gasPriceTier];
require(metric.args);
auto onOperation = [&]() auto onOperation = [&]()
{ {
if (_onOp) if (_onOp)
_onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext); _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
}; };
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
switch (inst) switch (inst)
{ {
case Instruction::STOP:
runGas = 0;
break;
case Instruction::SUICIDE:
require(1);
runGas = 0;
break;
case Instruction::SSTORE: case Instruction::SSTORE:
require(2);
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2]) if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas; runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2]) else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{ {
runGas = 0; runGas = c_sstoreClearGas;
_ext.sub.refunds += c_sstoreRefundGas; _ext.sub.refunds += c_sstoreRefundGas;
} }
else else
@ -94,52 +113,39 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
break; break;
case Instruction::SLOAD: case Instruction::SLOAD:
require(1);
runGas = c_sloadGas; runGas = c_sloadGas;
break; break;
// These all operate on memory and therefore potentially expand it: // These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE: case Instruction::MSTORE:
require(2);
newTempSize = (bigint)m_stack.back() + 32; newTempSize = (bigint)m_stack.back() + 32;
break; break;
case Instruction::MSTORE8: case Instruction::MSTORE8:
require(2);
newTempSize = (bigint)m_stack.back() + 1; newTempSize = (bigint)m_stack.back() + 1;
break; break;
case Instruction::MLOAD: case Instruction::MLOAD:
require(1);
newTempSize = (bigint)m_stack.back() + 32; newTempSize = (bigint)m_stack.back() + 32;
break; break;
case Instruction::RETURN: case Instruction::RETURN:
require(2);
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break; break;
case Instruction::SHA3: case Instruction::SHA3:
require(2);
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas; runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break; break;
case Instruction::CALLDATACOPY: case Instruction::CALLDATACOPY:
require(3);
copySize = m_stack[m_stack.size() - 3]; copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break; break;
case Instruction::CODECOPY: case Instruction::CODECOPY:
require(3);
copySize = m_stack[m_stack.size() - 3]; copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break; break;
case Instruction::EXTCODECOPY: case Instruction::EXTCODECOPY:
require(4);
copySize = m_stack[m_stack.size() - 4]; copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break; break;
case Instruction::BALANCE:
require(1);
runGas = c_balanceGas;
break;
case Instruction::LOG0: case Instruction::LOG0:
case Instruction::LOG1: case Instruction::LOG1:
case Instruction::LOG2: case Instruction::LOG2:
@ -147,7 +153,6 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
case Instruction::LOG4: case Instruction::LOG4:
{ {
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0; unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
require(n + 2);
runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2]; runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]); newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break; break;
@ -155,149 +160,27 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
require(7);
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1]; runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
if (!_ext.exists(asAddress(m_stack[m_stack.size() - 2])))
runGas += c_callNewAccountGas;
if (m_stack[m_stack.size() - 3] > 0)
runGas += c_callValueTransferGas;
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])); 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; break;
case Instruction::CREATE: case Instruction::CREATE:
{ {
require(3);
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]); newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas; runGas = c_createGas;
break; break;
} }
case Instruction::EXP: case Instruction::EXP:
{ {
require(2);
auto expon = m_stack[m_stack.size() - 2]; auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8)); runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break; break;
} }
default:;
case Instruction::BLOCKHASH:
require(1);
break;
case Instruction::PC:
case Instruction::MSIZE:
case Instruction::GAS:
case Instruction::JUMPDEST:
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::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:
break;
case Instruction::NOT:
case Instruction::ISZERO:
case Instruction::CALLDATALOAD:
case Instruction::EXTCODESIZE:
case Instruction::POP:
case Instruction::JUMP:
require(1);
break;
case Instruction::ADD:
case Instruction::MUL:
case Instruction::SUB:
case Instruction::DIV:
case Instruction::SDIV:
case Instruction::MOD:
case Instruction::SMOD:
case Instruction::LT:
case Instruction::GT:
case Instruction::SLT:
case Instruction::SGT:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
case Instruction::BYTE:
case Instruction::JUMPI:
case Instruction::SIGNEXTEND:
require(2);
break;
case Instruction::ADDMOD:
case Instruction::MULMOD:
require(3);
break;
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:
require(1 + (int)inst - (int)Instruction::DUP1);
break;
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:
require((int)inst - (int)Instruction::SWAP1 + 2);
break;
default:
BOOST_THROW_EXCEPTION(BadInstruction());
} }
newTempSize = (newTempSize + 31) / 32 * 32; newTempSize = (newTempSize + 31) / 32 * 32;

267
libevmcore/Instruction.cpp

@ -162,136 +162,136 @@ const std::map<std::string, Instruction> dev::eth::c_instructions =
}; };
static const std::map<Instruction, InstructionInfo> c_instructionInfo = static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ // Add, Args, Ret, SideEffects { // Add, Args, Ret, SideEffects, GasPriceTier
{ Instruction::STOP, { "STOP", 0, 0, 0, true } }, { Instruction::STOP, { "STOP", 0, 0, 0, true, ZeroTier } },
{ Instruction::ADD, { "ADD", 0, 2, 1, false } }, { Instruction::ADD, { "ADD", 0, 2, 1, false, VeryLowTier } },
{ Instruction::SUB, { "SUB", 0, 2, 1, false } }, { Instruction::SUB, { "SUB", 0, 2, 1, false, VeryLowTier } },
{ Instruction::MUL, { "MUL", 0, 2, 1, false } }, { Instruction::MUL, { "MUL", 0, 2, 1, false, LowTier } },
{ Instruction::DIV, { "DIV", 0, 2, 1, false } }, { Instruction::DIV, { "DIV", 0, 2, 1, false, LowTier } },
{ Instruction::SDIV, { "SDIV", 0, 2, 1, false } }, { Instruction::SDIV, { "SDIV", 0, 2, 1, false, LowTier } },
{ Instruction::MOD, { "MOD", 0, 2, 1, false } }, { Instruction::MOD, { "MOD", 0, 2, 1, false, LowTier } },
{ Instruction::SMOD, { "SMOD", 0, 2, 1, false } }, { Instruction::SMOD, { "SMOD", 0, 2, 1, false, LowTier } },
{ Instruction::EXP, { "EXP", 0, 2, 1, false } }, { Instruction::EXP, { "EXP", 0, 2, 1, false, SpecialTier } },
{ Instruction::NOT, { "NOT", 0, 1, 1, false } }, { Instruction::NOT, { "NOT", 0, 1, 1, false, VeryLowTier } },
{ Instruction::LT, { "LT", 0, 2, 1, false } }, { Instruction::LT, { "LT", 0, 2, 1, false, VeryLowTier } },
{ Instruction::GT, { "GT", 0, 2, 1, false } }, { Instruction::GT, { "GT", 0, 2, 1, false, VeryLowTier } },
{ Instruction::SLT, { "SLT", 0, 2, 1, false } }, { Instruction::SLT, { "SLT", 0, 2, 1, false, VeryLowTier } },
{ Instruction::SGT, { "SGT", 0, 2, 1, false } }, { Instruction::SGT, { "SGT", 0, 2, 1, false, VeryLowTier } },
{ Instruction::EQ, { "EQ", 0, 2, 1, false } }, { Instruction::EQ, { "EQ", 0, 2, 1, false, VeryLowTier } },
{ Instruction::ISZERO, { "ISZERO", 0, 1, 1, false } }, { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false, VeryLowTier } },
{ Instruction::AND, { "AND", 0, 2, 1, false } }, { Instruction::AND, { "AND", 0, 2, 1, false, VeryLowTier } },
{ Instruction::OR, { "OR", 0, 2, 1, false } }, { Instruction::OR, { "OR", 0, 2, 1, false, VeryLowTier } },
{ Instruction::XOR, { "XOR", 0, 2, 1, false } }, { Instruction::XOR, { "XOR", 0, 2, 1, false, VeryLowTier } },
{ Instruction::BYTE, { "BYTE", 0, 2, 1, false } }, { Instruction::BYTE, { "BYTE", 0, 2, 1, false, VeryLowTier } },
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false } }, { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, MidTier } },
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false } }, { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, MidTier } },
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false } }, { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, LowTier } },
{ Instruction::SHA3, { "SHA3", 0, 2, 1, false } }, { Instruction::SHA3, { "SHA3", 0, 2, 1, false, SpecialTier } },
{ Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false } }, { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false, BaseTier } },
{ Instruction::BALANCE, { "BALANCE", 0, 1, 1, false } }, { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false, ExtTier } },
{ Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false } }, { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false, BaseTier } },
{ Instruction::CALLER, { "CALLER", 0, 0, 1, false } }, { Instruction::CALLER, { "CALLER", 0, 0, 1, false, BaseTier } },
{ Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false } }, { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false, BaseTier } },
{ Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false } }, { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false, VeryLowTier } },
{ Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false } }, { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false, BaseTier } },
{ Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true } }, { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true, VeryLowTier } },
{ Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false } }, { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false, BaseTier } },
{ Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true } }, { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true, VeryLowTier } },
{ Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false } }, { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false, BaseTier } },
{ Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false } }, { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false, ExtTier } },
{ Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true } }, { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true, ExtTier } },
{ Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false } }, { Instruction::BLOCKHASH, { "BLOCKHASH", 0, 1, 1, false, ExtTier } },
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false } }, { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, BaseTier } },
{ Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, BaseTier } },
{ Instruction::NUMBER, { "NUMBER", 0, 0, 1, false } }, { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, BaseTier } },
{ Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false } }, { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, BaseTier } },
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false } }, { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, BaseTier } },
{ Instruction::POP, { "POP", 0, 1, 0, false } }, { Instruction::POP, { "POP", 0, 1, 0, false, BaseTier } },
{ Instruction::MLOAD, { "MLOAD", 0, 1, 1, false } }, { Instruction::MLOAD, { "MLOAD", 0, 1, 1, false, VeryLowTier } },
{ Instruction::MSTORE, { "MSTORE", 0, 2, 0, true } }, { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, VeryLowTier } },
{ Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true } }, { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true, VeryLowTier } },
{ Instruction::SLOAD, { "SLOAD", 0, 1, 1, false } }, { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false, SpecialTier } },
{ Instruction::SSTORE, { "SSTORE", 0, 2, 0, true } }, { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true, SpecialTier } },
{ Instruction::JUMP, { "JUMP", 0, 1, 0, true } }, { Instruction::JUMP, { "JUMP", 0, 1, 0, true, MidTier } },
{ Instruction::JUMPI, { "JUMPI", 0, 2, 0, true } }, { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true, HighTier } },
{ Instruction::PC, { "PC", 0, 0, 1, false } }, { Instruction::PC, { "PC", 0, 0, 1, false, BaseTier } },
{ Instruction::MSIZE, { "MSIZE", 0, 0, 1, false } }, { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, BaseTier } },
{ Instruction::GAS, { "GAS", 0, 0, 1, false } }, { Instruction::GAS, { "GAS", 0, 0, 1, false, BaseTier } },
{ Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0, true } }, { Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0, true, SpecialTier } },
{ Instruction::PUSH1, { "PUSH1", 1, 0, 1, false } }, { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH2, { "PUSH2", 2, 0, 1, false } }, { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH3, { "PUSH3", 3, 0, 1, false } }, { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH4, { "PUSH4", 4, 0, 1, false } }, { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH5, { "PUSH5", 5, 0, 1, false } }, { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH6, { "PUSH6", 6, 0, 1, false } }, { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH7, { "PUSH7", 7, 0, 1, false } }, { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH8, { "PUSH8", 8, 0, 1, false } }, { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH9, { "PUSH9", 9, 0, 1, false } }, { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH10, { "PUSH10", 10, 0, 1, false } }, { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH11, { "PUSH11", 11, 0, 1, false } }, { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH12, { "PUSH12", 12, 0, 1, false } }, { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH13, { "PUSH13", 13, 0, 1, false } }, { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH14, { "PUSH14", 14, 0, 1, false } }, { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH15, { "PUSH15", 15, 0, 1, false } }, { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH16, { "PUSH16", 16, 0, 1, false } }, { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH17, { "PUSH17", 17, 0, 1, false } }, { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH18, { "PUSH18", 18, 0, 1, false } }, { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH19, { "PUSH19", 19, 0, 1, false } }, { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH20, { "PUSH20", 20, 0, 1, false } }, { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH21, { "PUSH21", 21, 0, 1, false } }, { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH22, { "PUSH22", 22, 0, 1, false } }, { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH23, { "PUSH23", 23, 0, 1, false } }, { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH24, { "PUSH24", 24, 0, 1, false } }, { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH25, { "PUSH25", 25, 0, 1, false } }, { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH26, { "PUSH26", 26, 0, 1, false } }, { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH27, { "PUSH27", 27, 0, 1, false } }, { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH28, { "PUSH28", 28, 0, 1, false } }, { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH29, { "PUSH29", 29, 0, 1, false } }, { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH30, { "PUSH30", 30, 0, 1, false } }, { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH31, { "PUSH31", 31, 0, 1, false } }, { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false, VeryLowTier } },
{ Instruction::PUSH32, { "PUSH32", 32, 0, 1, false } }, { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false, VeryLowTier } },
{ Instruction::DUP1, { "DUP1", 0, 1, 2, false } }, { Instruction::DUP1, { "DUP1", 0, 1, 2, false, VeryLowTier } },
{ Instruction::DUP2, { "DUP2", 0, 2, 3, false } }, { Instruction::DUP2, { "DUP2", 0, 2, 3, false, VeryLowTier } },
{ Instruction::DUP3, { "DUP3", 0, 3, 4, false } }, { Instruction::DUP3, { "DUP3", 0, 3, 4, false, VeryLowTier } },
{ Instruction::DUP4, { "DUP4", 0, 4, 5, false } }, { Instruction::DUP4, { "DUP4", 0, 4, 5, false, VeryLowTier } },
{ Instruction::DUP5, { "DUP5", 0, 5, 6, false } }, { Instruction::DUP5, { "DUP5", 0, 5, 6, false, VeryLowTier } },
{ Instruction::DUP6, { "DUP6", 0, 6, 7, false } }, { Instruction::DUP6, { "DUP6", 0, 6, 7, false, VeryLowTier } },
{ Instruction::DUP7, { "DUP7", 0, 7, 8, false } }, { Instruction::DUP7, { "DUP7", 0, 7, 8, false, VeryLowTier } },
{ Instruction::DUP8, { "DUP8", 0, 8, 9, false } }, { Instruction::DUP8, { "DUP8", 0, 8, 9, false, VeryLowTier } },
{ Instruction::DUP9, { "DUP9", 0, 9, 10, false } }, { Instruction::DUP9, { "DUP9", 0, 9, 10, false, VeryLowTier } },
{ Instruction::DUP10, { "DUP10", 0, 10, 11, false } }, { Instruction::DUP10, { "DUP10", 0, 10, 11, false, VeryLowTier } },
{ Instruction::DUP11, { "DUP11", 0, 11, 12, false } }, { Instruction::DUP11, { "DUP11", 0, 11, 12, false, VeryLowTier } },
{ Instruction::DUP12, { "DUP12", 0, 12, 13, false } }, { Instruction::DUP12, { "DUP12", 0, 12, 13, false, VeryLowTier } },
{ Instruction::DUP13, { "DUP13", 0, 13, 14, false } }, { Instruction::DUP13, { "DUP13", 0, 13, 14, false, VeryLowTier } },
{ Instruction::DUP14, { "DUP14", 0, 14, 15, false } }, { Instruction::DUP14, { "DUP14", 0, 14, 15, false, VeryLowTier } },
{ Instruction::DUP15, { "DUP15", 0, 15, 16, false } }, { Instruction::DUP15, { "DUP15", 0, 15, 16, false, VeryLowTier } },
{ Instruction::DUP16, { "DUP16", 0, 16, 17, false } }, { Instruction::DUP16, { "DUP16", 0, 16, 17, false, VeryLowTier } },
{ Instruction::SWAP1, { "SWAP1", 0, 2, 2, false } }, { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false, VeryLowTier } },
{ Instruction::SWAP2, { "SWAP2", 0, 3, 3, false } }, { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false, VeryLowTier } },
{ Instruction::SWAP3, { "SWAP3", 0, 4, 4, false } }, { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false, VeryLowTier } },
{ Instruction::SWAP4, { "SWAP4", 0, 5, 5, false } }, { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false, VeryLowTier } },
{ Instruction::SWAP5, { "SWAP5", 0, 6, 6, false } }, { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false, VeryLowTier } },
{ Instruction::SWAP6, { "SWAP6", 0, 7, 7, false } }, { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false, VeryLowTier } },
{ Instruction::SWAP7, { "SWAP7", 0, 8, 8, false } }, { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false, VeryLowTier } },
{ Instruction::SWAP8, { "SWAP8", 0, 9, 9, false } }, { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false, VeryLowTier } },
{ Instruction::SWAP9, { "SWAP9", 0, 10, 10, false } }, { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false, VeryLowTier } },
{ Instruction::SWAP10, { "SWAP10", 0, 11, 11, false } }, { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false, VeryLowTier } },
{ Instruction::SWAP11, { "SWAP11", 0, 12, 12, false } }, { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false, VeryLowTier } },
{ Instruction::SWAP12, { "SWAP12", 0, 13, 13, false } }, { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false, VeryLowTier } },
{ Instruction::SWAP13, { "SWAP13", 0, 14, 14, false } }, { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false, VeryLowTier } },
{ Instruction::SWAP14, { "SWAP14", 0, 15, 15, false } }, { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false, VeryLowTier } },
{ Instruction::SWAP15, { "SWAP15", 0, 16, 16, false } }, { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false, VeryLowTier } },
{ Instruction::SWAP16, { "SWAP16", 0, 17, 17, false } }, { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false, VeryLowTier } },
{ Instruction::LOG0, { "LOG0", 0, 2, 0, true } }, { Instruction::LOG0, { "LOG0", 0, 2, 0, true, SpecialTier } },
{ Instruction::LOG1, { "LOG1", 0, 3, 0, true } }, { Instruction::LOG1, { "LOG1", 0, 3, 0, true, SpecialTier } },
{ Instruction::LOG2, { "LOG2", 0, 4, 0, true } }, { Instruction::LOG2, { "LOG2", 0, 4, 0, true, SpecialTier } },
{ Instruction::LOG3, { "LOG3", 0, 5, 0, true } }, { Instruction::LOG3, { "LOG3", 0, 5, 0, true, SpecialTier } },
{ Instruction::LOG4, { "LOG4", 0, 6, 0, true } }, { Instruction::LOG4, { "LOG4", 0, 6, 0, true, SpecialTier } },
{ Instruction::CREATE, { "CREATE", 0, 3, 1, true } }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true, SpecialTier } },
{ Instruction::CALL, { "CALL", 0, 7, 1, true } }, { Instruction::CALL, { "CALL", 0, 7, 1, true, SpecialTier } },
{ Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, SpecialTier } },
{ Instruction::RETURN, { "RETURN", 0, 2, 0, true } }, { Instruction::RETURN, { "RETURN", 0, 2, 0, true, ZeroTier } },
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true } } { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true, ZeroTier } }
}; };
string dev::eth::disassemble(bytes const& _mem) string dev::eth::disassemble(bytes const& _mem)
@ -326,12 +326,7 @@ InstructionInfo dev::eth::instructionInfo(Instruction _inst)
} }
catch (...) catch (...)
{ {
#ifndef BOOST_NO_EXCEPTIONS return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false, InvalidTier});
cwarn << "<INVALID_INSTRUCTION: " << toString((unsigned)_inst) << ">\n" << boost::current_exception_diagnostic_information();
#else
cwarn << "<INVALID_INSTRUCTION: " << toString((unsigned)_inst) << ">\n";
#endif
return InstructionInfo({"<INVALID_INSTRUCTION: " + toString((unsigned)_inst) + ">", 0, 0, 0, false});
} }
} }

14
libevmcore/Instruction.h

@ -223,6 +223,19 @@ inline Instruction logInstruction(unsigned _number)
return Instruction(unsigned(Instruction::LOG0) + _number); return Instruction(unsigned(Instruction::LOG0) + _number);
} }
enum Tier
{
ZeroTier = 0, // 0, Zero
BaseTier, // 2, Quick
VeryLowTier, // 3, Fastest
LowTier, // 5, Fast
MidTier, // 8, Mid
HighTier, // 10, Slow
ExtTier, // 20, Ext
SpecialTier, // multiparam or otherwise special
InvalidTier // Invalid.
};
/// Information structure for a particular instruction. /// Information structure for a particular instruction.
struct InstructionInfo struct InstructionInfo
{ {
@ -231,6 +244,7 @@ struct InstructionInfo
int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack). int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack).
int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed. int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed.
bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack
int gasPriceTier; ///< Tier for gas pricing.
}; };
/// Information on all the instructions. /// Information on all the instructions.

Loading…
Cancel
Save