Browse Source

Unrevert VM.

cl-refactor
Gav Wood 10 years ago
parent
commit
a3d39e784f
  1. 19
      libethereum/Client.cpp
  2. 2
      libethereum/Client.h
  3. 2
      libethereum/Executive.cpp
  4. 1
      libethereum/State.cpp
  5. 322
      libevm/VM.cpp
  6. 6
      libevm/VM.h
  7. 14
      libevm/VMFace.h

19
libethereum/Client.cpp

@ -87,7 +87,7 @@ void VersionChecker::setOk()
} }
} }
void Client::onBadBlock(Exception& _ex) void Client::onBadBlock(Exception& _ex) const
{ {
// BAD BLOCK!!! // BAD BLOCK!!!
bytes const* block = boost::get_error_info<errinfo_block>(_ex); bytes const* block = boost::get_error_info<errinfo_block>(_ex);
@ -125,6 +125,9 @@ void Client::onBadBlock(Exception& _ex)
// general block failure. // general block failure.
} }
if (string const* vmtraceJson = boost::get_error_info<errinfo_vmtrace>(_ex))
Json::Reader().parse(*vmtraceJson, report["hints"]["vmtrace"]);
if (vector<bytes> const* receipts = boost::get_error_info<errinfo_receipts>(_ex)) if (vector<bytes> const* receipts = boost::get_error_info<errinfo_receipts>(_ex))
{ {
report["hints"]["receipts"] = Json::arrayValue; report["hints"]["receipts"] = Json::arrayValue;
@ -178,9 +181,6 @@ void Client::onBadBlock(Exception& _ex)
if (!m_sentinel.empty()) if (!m_sentinel.empty())
{ {
if (string const* vmtraceJson = boost::get_error_info<errinfo_vmtrace>(_ex))
Json::Reader().parse(*vmtraceJson, report["hints"]["vmtrace"]);
jsonrpc::HttpClient client(m_sentinel); jsonrpc::HttpClient client(m_sentinel);
Sentinel rpc(client); Sentinel rpc(client);
try try
@ -860,7 +860,16 @@ void Client::checkWatchGarbage()
State Client::asOf(h256 const& _block) const State Client::asOf(h256 const& _block) const
{ {
return State(m_stateDB, bc(), _block); try
{
return State(m_stateDB, bc(), _block);
}
catch (Exception& ex)
{
ex << errinfo_block(bc().block(_block));
onBadBlock(ex);
return State();
}
} }
void Client::prepareForTransaction() void Client::prepareForTransaction()

2
libethereum/Client.h

@ -301,7 +301,7 @@ private:
/// Called when we have attempted to import a bad block. /// Called when we have attempted to import a bad block.
/// @warning May be called from any thread. /// @warning May be called from any thread.
void onBadBlock(Exception& _ex); void onBadBlock(Exception& _ex) const;
VersionChecker m_vc; ///< Dummy object to check & update the protocol version. VersionChecker m_vc; ///< Dummy object to check & update the protocol version.
CanonBlockChain m_bc; ///< Maintains block database. CanonBlockChain m_bc; ///< Maintains block database.

2
libethereum/Executive.cpp

@ -120,7 +120,7 @@ void StandardTrace::operator()(uint64_t _steps, Instruction inst, bigint newMemS
r["storage"] = storage; r["storage"] = storage;
} }
if (returned) if (returned || newContext)
r["depth"] = ext.depth; r["depth"] = ext.depth;
if (newContext) if (newContext)
r["address"] = ext.myAddress.hex(); r["address"] = ext.myAddress.hex();

1
libethereum/State.cpp

@ -594,6 +594,7 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire
for (auto const& tr: rlp[1]) for (auto const& tr: rlp[1])
{ {
StandardTrace st; StandardTrace st;
st.setShowMnemonics();
execute(lh, Transaction(tr.data(), CheckTransaction::Everything), Permanence::Committed, [&](uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM) { st(_steps, _inst, _newMemSize, _gasCost, _gas, _vm, _extVM); }); execute(lh, Transaction(tr.data(), CheckTransaction::Everything), Permanence::Committed, [&](uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM) { st(_steps, _inst, _newMemSize, _gasCost, _gas, _vm, _extVM); });
ret += (ret.empty() ? "[" : ",") + st.json(); ret += (ret.empty() ? "[" : ",") + st.json();

322
libevm/VM.cpp

@ -45,165 +45,169 @@ static array<InstructionMetric, 256> metrics()
return s_ret; return s_ret;
} }
bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) void VM::checkRequirements(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, Instruction _inst)
{ {
// Reset leftovers from possible previous run static const auto c_metrics = metrics();
m_curPC = 0; auto& metric = c_metrics[static_cast<size_t>(_inst)];
m_jumpDests.clear();
m_stack.reserve((unsigned)c_stackLimit); if (metric.gasPriceTier == InvalidTier)
BOOST_THROW_EXCEPTION(BadInstruction());
unique_ptr<CallParameters> callParams; // FEES...
bigint runGas = c_tierStepGas[metric.gasPriceTier];
bigint newTempSize = m_temp.size();
bigint copySize = 0;
static const array<InstructionMetric, 256> c_metrics = metrics(); // should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; require(metric.args, metric.ret);
auto gasForMem = [](bigint _size) -> bigint
auto onOperation = [&]()
{ {
bigint s = _size / 32; if (_onOp)
return (bigint)c_memoryGas * s + s * s / c_quadCoeffDiv; _onOp(m_steps, _inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
}; };
if (m_jumpDests.empty()) auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
for (unsigned i = 0; i < _ext.code.size(); ++i)
switch (_inst)
{
case Instruction::SSTORE:
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{ {
if (_ext.code[i] == (byte)Instruction::JUMPDEST) runGas = c_sstoreResetGas;
m_jumpDests.push_back(i); _ext.sub.refunds += c_sstoreRefundGas;
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
} }
u256 nextPC = m_curPC + 1; else
for (uint64_t steps = 0; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++steps) runGas = c_sstoreResetGas;
break;
case Instruction::SLOAD:
runGas = c_sloadGas;
break;
// These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::MSTORE8:
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
case Instruction::JUMPDEST:
runGas = 1;
break;
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{ {
// INSTRUCTION... unsigned n = (unsigned)_inst - (unsigned)Instruction::LOG0;
Instruction inst = (Instruction)_ext.getCode(m_curPC); runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
auto metric = c_metrics[(int)inst]; newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
int gasPriceTier = metric.gasPriceTier; break;
}
if (gasPriceTier == InvalidTier)
BOOST_THROW_EXCEPTION(BadInstruction());
// FEES...
bigint runGas = c_tierStepGas[metric.gasPriceTier];
bigint newTempSize = m_temp.size();
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);
require(metric.args, metric.ret);
auto onOperation = [&]()
{
if (_onOp)
_onOp(steps, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
};
switch (inst)
{
case Instruction::SSTORE:
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
runGas = c_sstoreResetGas;
_ext.sub.refunds += c_sstoreRefundGas;
}
else
runGas = c_sstoreResetGas;
break;
case Instruction::SLOAD: case Instruction::CALL:
runGas = c_sloadGas; case Instruction::CALLCODE:
break; runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
if (_inst != Instruction::CALLCODE && !_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]));
break;
case Instruction::CREATE:
{
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
default:;
}
// These all operate on memory and therefore potentially expand it: auto gasForMem = [](bigint _size) -> bigint
case Instruction::MSTORE: {
newTempSize = (bigint)m_stack.back() + 32; bigint s = _size / 32;
break; return (bigint)c_memoryGas * s + s * s / c_quadCoeffDiv;
case Instruction::MSTORE8: };
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
case Instruction::JUMPDEST: newTempSize = (newTempSize + 31) / 32 * 32;
runGas = 1; if (newTempSize > m_temp.size())
break; runGas += gasForMem(newTempSize) - gasForMem(m_temp.size());
runGas += c_copyGas * ((copySize + 31) / 32);
case Instruction::LOG0: onOperation();
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
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]);
break;
}
case Instruction::CALL: if (io_gas < runGas)
case Instruction::CALLCODE: BOOST_THROW_EXCEPTION(OutOfGas());
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
if (inst != Instruction::CALLCODE && !_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]));
break;
case Instruction::CREATE: io_gas -= (u256)runGas;
{
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
default:;
}
newTempSize = (newTempSize + 31) / 32 * 32; if (newTempSize > m_temp.size())
if (newTempSize > m_temp.size()) m_temp.resize((size_t)newTempSize);
runGas += gasForMem(newTempSize) - gasForMem(m_temp.size()); }
runGas += c_copyGas * ((copySize + 31) / 32);
onOperation(); bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
{
m_stack.reserve((unsigned)c_stackLimit);
if (io_gas < runGas) for (size_t i = 0; i < _ext.code.size(); ++i)
BOOST_THROW_EXCEPTION(OutOfGas()); {
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.push_back(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (size_t)Instruction::PUSH1 + 1;
}
io_gas -= (u256)runGas; auto verifyJumpDest = [](u256 const& _dest, std::vector<uint64_t> const& _validDests)
{
auto nextPC = static_cast<uint64_t>(_dest);
if (!std::binary_search(_validDests.begin(), _validDests.end(), nextPC) || _dest > std::numeric_limits<uint64_t>::max())
BOOST_THROW_EXCEPTION(BadJumpDestination());
return nextPC;
};
if (newTempSize > m_temp.size()) m_steps = 0;
m_temp.resize((size_t)newTempSize); for (auto nextPC = m_curPC + 1; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++m_steps)
{
Instruction inst = (Instruction)_ext.getCode(m_curPC);
checkRequirements(io_gas, _ext, _onOp, inst);
// EXECUTE...
switch (inst) switch (inst)
{ {
case Instruction::ADD: case Instruction::ADD:
@ -299,7 +303,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::SIGNEXTEND: case Instruction::SIGNEXTEND:
if (m_stack.back() < 31) if (m_stack.back() < 31)
{ {
unsigned const testBit(m_stack.back() * 8 + 7); auto testBit = static_cast<unsigned>(m_stack.back()) * 8 + 7;
u256& number = m_stack[m_stack.size() - 2]; u256& number = m_stack[m_stack.size() - 2];
u256 mask = ((u256(1) << testBit) - 1); u256 mask = ((u256(1) << testBit) - 1);
if (boost::multiprecision::bit_test(number, testBit)) if (boost::multiprecision::bit_test(number, testBit))
@ -480,7 +484,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::DUP15: case Instruction::DUP15:
case Instruction::DUP16: case Instruction::DUP16:
{ {
auto n = 1 + (int)inst - (int)Instruction::DUP1; auto n = 1 + (unsigned)inst - (unsigned)Instruction::DUP1;
m_stack.push_back(m_stack[m_stack.size() - n]); m_stack.push_back(m_stack[m_stack.size() - n]);
break; break;
} }
@ -501,7 +505,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::SWAP15: case Instruction::SWAP15:
case Instruction::SWAP16: case Instruction::SWAP16:
{ {
unsigned n = (int)inst - (int)Instruction::SWAP1 + 2; auto n = (unsigned)inst - (unsigned)Instruction::SWAP1 + 2;
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;
@ -535,18 +539,12 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::JUMP: case Instruction::JUMP:
nextPC = m_stack.back(); nextPC = verifyJumpDest(m_stack.back(), m_jumpDests);
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::JUMPI: case Instruction::JUMPI:
if (m_stack[m_stack.size() - 2]) if (m_stack[m_stack.size() - 2])
{ nextPC = verifyJumpDest(m_stack.back(), m_jumpDests);
nextPC = m_stack.back();
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
}
m_stack.pop_back(); m_stack.pop_back();
m_stack.pop_back(); m_stack.pop_back();
break; break;
@ -598,7 +596,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
break; break;
case Instruction::CREATE: case Instruction::CREATE:
{ {
u256 endowment = m_stack.back(); auto endowment = m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back(); unsigned initOff = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
@ -614,16 +612,14 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
{ {
if (!callParams) CallParameters callParams;
callParams.reset(new CallParameters); callParams.gas = m_stack.back();
callParams->gas = m_stack.back();
if (m_stack[m_stack.size() - 3] > 0) if (m_stack[m_stack.size() - 3] > 0)
callParams->gas += c_callStipend; callParams.gas += c_callStipend;
m_stack.pop_back(); m_stack.pop_back();
callParams->codeAddress = asAddress(m_stack.back()); callParams.codeAddress = asAddress(m_stack.back());
m_stack.pop_back(); m_stack.pop_back();
callParams->value = m_stack.back(); callParams.value = m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
unsigned inOff = (unsigned)m_stack.back(); unsigned inOff = (unsigned)m_stack.back();
@ -635,19 +631,19 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
unsigned outSize = (unsigned)m_stack.back(); unsigned outSize = (unsigned)m_stack.back();
m_stack.pop_back(); m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= callParams->value && _ext.depth < 1024) if (_ext.balance(_ext.myAddress) >= callParams.value && _ext.depth < 1024)
{ {
callParams->onOp = _onOp; callParams.onOp = _onOp;
callParams->senderAddress = _ext.myAddress; callParams.senderAddress = _ext.myAddress;
callParams->receiveAddress = inst == Instruction::CALL ? callParams->codeAddress : callParams->senderAddress; callParams.receiveAddress = inst == Instruction::CALL ? callParams.codeAddress : callParams.senderAddress;
callParams->data = bytesConstRef(m_temp.data() + inOff, inSize); callParams.data = bytesConstRef(m_temp.data() + inOff, inSize);
callParams->out = bytesRef(m_temp.data() + outOff, outSize); callParams.out = bytesRef(m_temp.data() + outOff, outSize);
m_stack.push_back(_ext.call(*callParams)); m_stack.push_back(_ext.call(callParams));
} }
else else
m_stack.push_back(0); m_stack.push_back(0);
io_gas += callParams->gas; io_gas += callParams.gas;
break; break;
} }
case Instruction::RETURN: case Instruction::RETURN:

6
libevm/VM.h

@ -54,16 +54,18 @@ class VM: public VMFace
public: public:
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final; virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
u256 curPC() const { return m_curPC; } uint64_t curPC() const { return m_curPC; }
bytes const& memory() const { return m_temp; } bytes const& memory() const { return m_temp; }
u256s const& stack() const { return m_stack; } u256s const& stack() const { return m_stack; }
private: private:
void checkRequirements(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, Instruction _inst);
void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } } void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } }
void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
u256 m_curPC = 0; uint64_t m_curPC = 0;
uint64_t m_steps = 0;
bytes m_temp; bytes m_temp;
u256s m_stack; u256s m_stack;
std::vector<uint64_t> m_jumpDests; std::vector<uint64_t> m_jumpDests;

14
libevm/VMFace.h

@ -25,14 +25,14 @@ namespace dev
namespace eth namespace eth
{ {
#define ETH_SIMPLE_EXCEPTION_VM(X) struct X: virtual VMException { public X(): VMException(#X) {} };
struct VMException: virtual Exception {}; struct VMException: virtual Exception {};
struct BreakPointHit: virtual VMException {}; #define ETH_SIMPLE_EXCEPTION_VM(X) struct X: virtual VMException { const char* what() const noexcept override { return #X; } }
struct BadInstruction: virtual VMException {}; ETH_SIMPLE_EXCEPTION_VM(BreakPointHit);
struct BadJumpDestination: virtual VMException {}; ETH_SIMPLE_EXCEPTION_VM(BadInstruction);
struct OutOfGas: virtual VMException {}; ETH_SIMPLE_EXCEPTION_VM(BadJumpDestination);
struct OutOfStack: virtual VMException {}; ETH_SIMPLE_EXCEPTION_VM(OutOfGas);
struct StackUnderflow: virtual VMException {}; ETH_SIMPLE_EXCEPTION_VM(OutOfStack);
ETH_SIMPLE_EXCEPTION_VM(StackUnderflow);
/// EVM Virtual Machine interface /// EVM Virtual Machine interface
class VMFace class VMFace

Loading…
Cancel
Save