Browse Source

Merge pull request #408 from CJentzsch/bugfix

Changing gas cost to zero at stackunderflow
cl-refactor
Gav Wood 10 years ago
parent
commit
484f6b7774
  1. 121
      libevm/VM.h
  2. 2
      libevmface/Instruction.cpp
  3. 3
      test/vm.cpp

121
libevm/VM.h

@ -110,6 +110,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::SUICIDE: case Instruction::SUICIDE:
require(1);
runGas = 0; runGas = 0;
break; break;
@ -124,6 +125,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::SLOAD: case Instruction::SLOAD:
require(1);
runGas = c_sloadGas; runGas = c_sloadGas;
break; break;
@ -163,15 +165,11 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::BALANCE: case Instruction::BALANCE:
require(1);
runGas = c_balanceGas; runGas = c_balanceGas;
break; break;
case Instruction::CALL: case Instruction::CALL:
require(7);
runGas = 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: case Instruction::CALLCODE:
require(7); require(7);
runGas = c_callGas + m_stack[m_stack.size() - 1]; runGas = c_callGas + m_stack[m_stack.size() - 1];
@ -188,35 +186,16 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
} }
case Instruction::ADD: case Instruction::PC:
case Instruction::MUL: case Instruction::MSIZE:
case Instruction::SUB: case Instruction::GAS:
case Instruction::DIV: case Instruction::JUMPDEST:
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::ADDRESS:
case Instruction::ORIGIN: case Instruction::ORIGIN:
case Instruction::CALLER: case Instruction::CALLER:
case Instruction::CALLVALUE: case Instruction::CALLVALUE:
case Instruction::CALLDATALOAD:
case Instruction::CALLDATASIZE: case Instruction::CALLDATASIZE:
case Instruction::CODESIZE: case Instruction::CODESIZE:
case Instruction::EXTCODESIZE:
case Instruction::GASPRICE: case Instruction::GASPRICE:
case Instruction::PREVHASH: case Instruction::PREVHASH:
case Instruction::COINBASE: case Instruction::COINBASE:
@ -256,7 +235,39 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::PUSH30: case Instruction::PUSH30:
case Instruction::PUSH31: case Instruction::PUSH31:
case Instruction::PUSH32: case Instruction::PUSH32:
break;
case Instruction::NEG:
case Instruction::NOT:
case Instruction::CALLDATALOAD:
case Instruction::EXTCODESIZE:
case Instruction::POP: 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::EXP:
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:
require(2);
break;
case Instruction::ADDMOD:
case Instruction::MULMOD:
require(3);
break;
case Instruction::DUP1: case Instruction::DUP1:
case Instruction::DUP2: case Instruction::DUP2:
case Instruction::DUP3: case Instruction::DUP3:
@ -273,6 +284,8 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::DUP14: case Instruction::DUP14:
case Instruction::DUP15: case Instruction::DUP15:
case Instruction::DUP16: case Instruction::DUP16:
require(1 + (int)inst - (int)Instruction::DUP1);
break;
case Instruction::SWAP1: case Instruction::SWAP1:
case Instruction::SWAP2: case Instruction::SWAP2:
case Instruction::SWAP3: case Instruction::SWAP3:
@ -289,12 +302,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::SWAP14: case Instruction::SWAP14:
case Instruction::SWAP15: case Instruction::SWAP15:
case Instruction::SWAP16: case Instruction::SWAP16:
case Instruction::JUMP: require((int)inst - (int)Instruction::SWAP1 + 2);
case Instruction::JUMPI:
case Instruction::PC:
case Instruction::MSIZE:
case Instruction::GAS:
case Instruction::JUMPDEST:
break; break;
default: default:
BOOST_THROW_EXCEPTION(BadInstruction()); BOOST_THROW_EXCEPTION(BadInstruction());
@ -324,44 +332,36 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
{ {
case Instruction::ADD: case Instruction::ADD:
//pops two items and pushes S[-1] + S[-2] mod 2^256. //pops two items and pushes S[-1] + S[-2] mod 2^256.
require(2);
m_stack[m_stack.size() - 2] += m_stack.back(); m_stack[m_stack.size() - 2] += m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::MUL: case Instruction::MUL:
//pops two items and pushes S[-1] * S[-2] mod 2^256. //pops two items and pushes S[-1] * S[-2] mod 2^256.
require(2);
m_stack[m_stack.size() - 2] *= m_stack.back(); m_stack[m_stack.size() - 2] *= m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SUB: case Instruction::SUB:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2]; m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::DIV: case Instruction::DIV:
require(2);
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() / m_stack[m_stack.size() - 2] : 0; m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() / m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SDIV: case Instruction::SDIV:
require(2);
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0; m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::MOD: case Instruction::MOD:
require(2);
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() % m_stack[m_stack.size() - 2] : 0; m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() % m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SMOD: case Instruction::SMOD:
require(2);
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0; m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::EXP: case Instruction::EXP:
{ {
require(2);
auto base = m_stack.back(); auto base = m_stack.back();
auto expon = m_stack[m_stack.size() - 2]; auto expon = m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
@ -369,73 +369,59 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
} }
case Instruction::NEG: case Instruction::NEG:
require(1);
m_stack.back() = ~(m_stack.back() - 1); m_stack.back() = ~(m_stack.back() - 1);
break; break;
case Instruction::LT: case Instruction::LT:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0; m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::GT: case Instruction::GT:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0; m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SLT: case Instruction::SLT:
require(2);
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SGT: case Instruction::SGT:
require(2);
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::EQ: case Instruction::EQ:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0; m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::NOT: case Instruction::NOT:
require(1);
m_stack.back() = m_stack.back() ? 0 : 1; m_stack.back() = m_stack.back() ? 0 : 1;
break; break;
case Instruction::AND: case Instruction::AND:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2]; m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::OR: case Instruction::OR:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2]; m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::XOR: case Instruction::XOR:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2]; m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::BYTE: case Instruction::BYTE:
require(2);
m_stack[m_stack.size() - 2] = m_stack.back() < 32 ? (m_stack[m_stack.size() - 2] >> (unsigned)(8 * (31 - m_stack.back()))) & 0xff : 0; m_stack[m_stack.size() - 2] = m_stack.back() < 32 ? (m_stack[m_stack.size() - 2] >> (unsigned)(8 * (31 - m_stack.back()))) & 0xff : 0;
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::ADDMOD: case Instruction::ADDMOD:
require(3);
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) + bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]); m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) + bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::MULMOD: case Instruction::MULMOD:
require(3);
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) * bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]); m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) * bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SHA3: case Instruction::SHA3:
{ {
require(2);
unsigned inOff = (unsigned)m_stack.back(); unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back(); unsigned inSize = (unsigned)m_stack.back();
@ -451,7 +437,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::BALANCE: case Instruction::BALANCE:
{ {
require(1);
m_stack.back() = _ext.balance(asAddress(m_stack.back())); m_stack.back() = _ext.balance(asAddress(m_stack.back()));
break; break;
} }
@ -463,7 +448,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::CALLDATALOAD: case Instruction::CALLDATALOAD:
{ {
require(1);
if ((unsigned)m_stack.back() + 31 < _ext.data.size()) if ((unsigned)m_stack.back() + 31 < _ext.data.size())
m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back()); m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back());
else else
@ -480,7 +464,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::CALLDATACOPY: case Instruction::CALLDATACOPY:
{ {
require(3);
unsigned mf = (unsigned)m_stack.back(); unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back(); unsigned cf = (unsigned)m_stack.back();
@ -497,7 +480,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::CODECOPY: case Instruction::CODECOPY:
{ {
require(3);
unsigned mf = (unsigned)m_stack.back(); unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back(); unsigned cf = (unsigned)m_stack.back();
@ -510,12 +492,10 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
} }
case Instruction::EXTCODESIZE: case Instruction::EXTCODESIZE:
require(1);
m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size(); m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size();
break; break;
case Instruction::EXTCODECOPY: case Instruction::EXTCODECOPY:
{ {
require(4);
Address a = asAddress(m_stack.back()); Address a = asAddress(m_stack.back());
m_stack.pop_back(); m_stack.pop_back();
unsigned mf = (unsigned)m_stack.back(); unsigned mf = (unsigned)m_stack.back();
@ -591,7 +571,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
} }
case Instruction::POP: case Instruction::POP:
require(1);
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::DUP1: case Instruction::DUP1:
@ -612,7 +591,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::DUP16: case Instruction::DUP16:
{ {
auto n = 1 + (int)inst - (int)Instruction::DUP1; auto n = 1 + (int)inst - (int)Instruction::DUP1;
require(n);
m_stack.push_back(m_stack[m_stack.size() - n]); m_stack.push_back(m_stack[m_stack.size() - n]);
break; break;
} }
@ -634,7 +612,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::SWAP16: case Instruction::SWAP16:
{ {
unsigned n = (int)inst - (int)Instruction::SWAP1 + 2; unsigned n = (int)inst - (int)Instruction::SWAP1 + 2;
require(n);
auto d = m_stack.back(); auto d = m_stack.back();
m_stack.back() = m_stack[m_stack.size() - n]; m_stack.back() = m_stack[m_stack.size() - n];
m_stack[m_stack.size() - n] = d; m_stack[m_stack.size() - n] = d;
@ -642,13 +619,11 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
} }
case Instruction::MLOAD: case Instruction::MLOAD:
{ {
require(1);
m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back()); m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back());
break; break;
} }
case Instruction::MSTORE: case Instruction::MSTORE:
{ {
require(2);
*(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2]; *(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2];
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
@ -656,31 +631,26 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
} }
case Instruction::MSTORE8: case Instruction::MSTORE8:
{ {
require(2);
m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff); m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff);
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
} }
case Instruction::SLOAD: case Instruction::SLOAD:
require(1);
m_stack.back() = _ext.store(m_stack.back()); m_stack.back() = _ext.store(m_stack.back());
break; break;
case Instruction::SSTORE: case Instruction::SSTORE:
require(2);
_ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]); _ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]);
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::JUMP: case Instruction::JUMP:
require(1);
nextPC = m_stack.back(); nextPC = m_stack.back();
if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST) if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST)
BOOST_THROW_EXCEPTION(BadJumpDestination()); BOOST_THROW_EXCEPTION(BadJumpDestination());
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::JUMPI: case Instruction::JUMPI:
require(2);
if (m_stack[m_stack.size() - 2]) if (m_stack[m_stack.size() - 2])
{ {
nextPC = m_stack.back(); nextPC = m_stack.back();
@ -703,8 +673,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break; break;
case Instruction::CREATE: case Instruction::CREATE:
{ {
require(3);
u256 endowment = m_stack.back(); u256 endowment = m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back(); unsigned initOff = (unsigned)m_stack.back();
@ -726,8 +694,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
{ {
require(7);
u256 gas = m_stack.back(); u256 gas = m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
Address receiveAddress = asAddress(m_stack.back()); Address receiveAddress = asAddress(m_stack.back());
@ -759,8 +725,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
} }
case Instruction::RETURN: case Instruction::RETURN:
{ {
require(2);
unsigned b = (unsigned)m_stack.back(); unsigned b = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned s = (unsigned)m_stack.back(); unsigned s = (unsigned)m_stack.back();
@ -770,7 +734,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
} }
case Instruction::SUICIDE: case Instruction::SUICIDE:
{ {
require(1);
Address dest = asAddress(m_stack.back()); Address dest = asAddress(m_stack.back());
_ext.suicide(dest); _ext.suicide(dest);
// ...follow through to... // ...follow through to...

2
libevmface/Instruction.cpp

@ -321,5 +321,5 @@ InstructionInfo dev::eth::instructionInfo(Instruction _inst)
bool dev::eth::isValidInstruction(Instruction _inst) bool dev::eth::isValidInstruction(Instruction _inst)
{ {
return c_instructionInfo.count(_inst); return !!c_instructionInfo.count(_inst);
} }

3
test/vm.cpp

@ -24,7 +24,7 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#define FILL_TESTS //#define FILL_TESTS
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
@ -751,4 +751,3 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest)
{ {
dev::test::executeTests("vmSystemOperationsTest"); dev::test::executeTests("vmSystemOperationsTest");
} }

Loading…
Cancel
Save