diff --git a/alethzero/Main.ui b/alethzero/Main.ui index e5e5a9f56..2ce00b0e3 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -173,6 +173,7 @@ + @@ -2055,6 +2056,17 @@ font-size: 14pt Clear Pe&nd&ing + + + true + + + false + + + Use &LLVM-EVM + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e15d08ab8..8be46e7ca 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -644,6 +645,7 @@ void Main::writeSettings() s.setValue("url", ui->urlEdit->text()); s.setValue("privateChain", m_privateChain); s.setValue("verbosity", ui->verbosity->value()); + s.setValue("jitvm", ui->jitvm->isChecked()); bytes d = m_webThree->saveNodes(); if (d.size()) @@ -718,6 +720,7 @@ void Main::readSettings(bool _skipGeometry) m_privateChain = s.value("privateChain", "").toString(); ui->usePrivate->setChecked(m_privateChain.size()); ui->verbosity->setValue(s.value("verbosity", 1).toInt()); + ui->jitvm->setChecked(s.value("jitvm", true).toBool()); ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html on_urlEdit_returnPressed(); @@ -817,6 +820,12 @@ void Main::on_usePrivate_triggered() on_killBlockchain_triggered(); } +void Main::on_jitvm_triggered() +{ + bool jit = ui->jitvm->isChecked(); + VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); +} + void Main::on_urlEdit_returnPressed() { QString s = ui->urlEdit->text(); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index bb79e59ef..5a331df7d 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -156,6 +156,7 @@ private slots: void on_importKeyFile_triggered(); void on_post_clicked(); void on_newIdentity_triggered(); + void on_jitvm_triggered(); void refreshWhisper(); void refreshBlockChain(); diff --git a/libevm/VM.cpp b/libevm/VM.cpp index b8452e4f5..4307d9da0 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -31,3 +31,763 @@ void VM::reset(u256 _gas) noexcept m_curPC = 0; m_jumpDests.clear(); } + +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) +{ + auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; + + if (m_jumpDests.empty()) + for (unsigned i = 0; i < _ext.code.size(); ++i) + if (_ext.code[i] == (byte)Instruction::JUMPDEST) + m_jumpDests.insert(i); + 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; + auto osteps = _steps; + for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1) + { + // INSTRUCTION... + Instruction inst = (Instruction)_ext.getCode(m_curPC); + + // FEES... + bigint runGas = c_stepGas; + bigint newTempSize = m_temp.size(); + bigint copySize = 0; + + auto onOperation = [&]() + { + if (_onOp) + _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(onOperation); + + switch (inst) + { + case Instruction::STOP: + runGas = 0; + break; + + case Instruction::SUICIDE: + require(1); + runGas = 0; + break; + + case Instruction::SSTORE: + require(2); + 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 = 0; + _ext.sub.refunds += c_sstoreRefundGas; + } + else + runGas = c_sstoreResetGas; + break; + + case Instruction::SLOAD: + require(1); + runGas = c_sloadGas; + break; + + // These all operate on memory and therefore potentially expand it: + case Instruction::MSTORE: + require(2); + newTempSize = (bigint)m_stack.back() + 32; + break; + case Instruction::MSTORE8: + require(2); + newTempSize = (bigint)m_stack.back() + 1; + break; + case Instruction::MLOAD: + require(1); + newTempSize = (bigint)m_stack.back() + 32; + break; + case Instruction::RETURN: + require(2); + newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); + break; + case Instruction::SHA3: + require(2); + 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: + require(3); + copySize = m_stack[m_stack.size() - 3]; + newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); + break; + case Instruction::CODECOPY: + require(3); + copySize = m_stack[m_stack.size() - 3]; + newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); + break; + case Instruction::EXTCODECOPY: + require(4); + copySize = m_stack[m_stack.size() - 4]; + newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); + break; + + case Instruction::BALANCE: + require(1); + runGas = c_balanceGas; + break; + case Instruction::LOG0: + case Instruction::LOG1: + case Instruction::LOG2: + case Instruction::LOG3: + case Instruction::LOG4: + { + 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]; + newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]); + break; + } + + case Instruction::CALL: + case Instruction::CALLCODE: + require(7); + runGas = (bigint)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::CREATE: + { + require(3); + newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]); + runGas = c_createGas; + break; + } + case Instruction::EXP: + { + require(2); + auto expon = m_stack[m_stack.size() - 2]; + runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8)); + break; + } + + 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; + if (newTempSize > m_temp.size()) + runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32; + runGas += c_copyGas * (copySize + 31) / 32; + + onOperation(); +// if (_onOp) +// _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext); + + if (m_gas < runGas) + { + // Out of gas! + m_gas = 0; + BOOST_THROW_EXCEPTION(OutOfGas()); + } + + m_gas = (u256)((bigint)m_gas - runGas); + + if (newTempSize > m_temp.size()) + m_temp.resize((size_t)newTempSize); + + // EXECUTE... + switch (inst) + { + case Instruction::ADD: + //pops two items and pushes S[-1] + S[-2] mod 2^256. + m_stack[m_stack.size() - 2] += m_stack.back(); + m_stack.pop_back(); + break; + case Instruction::MUL: + //pops two items and pushes S[-1] * S[-2] mod 2^256. + m_stack[m_stack.size() - 2] *= m_stack.back(); + m_stack.pop_back(); + break; + case Instruction::SUB: + m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + break; + case Instruction::DIV: + 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(); + break; + case Instruction::SDIV: + 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(); + break; + case Instruction::MOD: + 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(); + break; + case Instruction::SMOD: + 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(); + break; + case Instruction::EXP: + { + auto base = m_stack.back(); + auto expon = m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256); + break; + } + case Instruction::NOT: + m_stack.back() = ~m_stack.back(); + break; + case Instruction::LT: + m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; + case Instruction::GT: + m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; + case Instruction::SLT: + m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; + m_stack.pop_back(); + break; + case Instruction::SGT: + m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; + m_stack.pop_back(); + break; + case Instruction::EQ: + m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; + case Instruction::ISZERO: + m_stack.back() = m_stack.back() ? 0 : 1; + break; + case Instruction::AND: + m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + break; + case Instruction::OR: + m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + break; + case Instruction::XOR: + m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + break; + case Instruction::BYTE: + 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(); + break; + case Instruction::ADDMOD: + 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(); + break; + case Instruction::MULMOD: + 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(); + break; + case Instruction::SIGNEXTEND: + if (m_stack.back() < 31) + { + unsigned const testBit(m_stack.back() * 8 + 7); + u256& number = m_stack[m_stack.size() - 2]; + u256 mask = ((u256(1) << testBit) - 1); + if (boost::multiprecision::bit_test(number, testBit)) + number |= ~mask; + else + number &= mask; + } + m_stack.pop_back(); + break; + case Instruction::SHA3: + { + unsigned inOff = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned inSize = (unsigned)m_stack.back(); + m_stack.pop_back(); + m_stack.push_back(sha3(bytesConstRef(m_temp.data() + inOff, inSize))); + break; + } + case Instruction::ADDRESS: + m_stack.push_back(fromAddress(_ext.myAddress)); + break; + case Instruction::ORIGIN: + m_stack.push_back(fromAddress(_ext.origin)); + break; + case Instruction::BALANCE: + { + m_stack.back() = _ext.balance(asAddress(m_stack.back())); + break; + } + case Instruction::CALLER: + m_stack.push_back(fromAddress(_ext.caller)); + break; + case Instruction::CALLVALUE: + m_stack.push_back(_ext.value); + break; + case Instruction::CALLDATALOAD: + { + if ((unsigned)m_stack.back() + (uint64_t)31 < _ext.data.size()) + m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back()); + else + { + h256 r; + for (uint64_t i = (unsigned)m_stack.back(), e = (unsigned)m_stack.back() + (uint64_t)32, j = 0; i < e; ++i, ++j) + r[j] = i < _ext.data.size() ? _ext.data[i] : 0; + m_stack.back() = (u256)r; + } + break; + } + case Instruction::CALLDATASIZE: + m_stack.push_back(_ext.data.size()); + break; + case Instruction::CODESIZE: + m_stack.push_back(_ext.code.size()); + break; + case Instruction::EXTCODESIZE: + m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size(); + break; + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::EXTCODECOPY: + { + Address a; + if (inst == Instruction::EXTCODECOPY) + { + a = asAddress(m_stack.back()); + m_stack.pop_back(); + } + unsigned offset = (unsigned)m_stack.back(); + m_stack.pop_back(); + u256 index = m_stack.back(); + m_stack.pop_back(); + unsigned size = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned sizeToBeCopied; + switch(inst) + { + case Instruction::CALLDATACOPY: + sizeToBeCopied = index + (bigint)size > (u256)_ext.data.size() ? (u256)_ext.data.size() < index ? 0 : _ext.data.size() - (unsigned)index : size; + memcpy(m_temp.data() + offset, _ext.data.data() + (unsigned)index, sizeToBeCopied); + break; + case Instruction::CODECOPY: + sizeToBeCopied = index + (bigint)size > (u256)_ext.code.size() ? (u256)_ext.code.size() < index ? 0 : _ext.code.size() - (unsigned)index : size; + memcpy(m_temp.data() + offset, _ext.code.data() + (unsigned)index, sizeToBeCopied); + break; + case Instruction::EXTCODECOPY: + sizeToBeCopied = index + (bigint)size > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < index ? 0 : _ext.codeAt(a).size() - (unsigned)index : size; + memcpy(m_temp.data() + offset, _ext.codeAt(a).data() + (unsigned)index, sizeToBeCopied); + break; + default: + // this is unreachable, but if someone introduces a bug in the future, he may get here. + assert(false); + BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested.")); + break; + } + memset(m_temp.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied); + break; + } + case Instruction::GASPRICE: + m_stack.push_back(_ext.gasPrice); + break; + case Instruction::BLOCKHASH: + m_stack.back() = (u256)_ext.blockhash(m_stack.back()); + break; + case Instruction::COINBASE: + m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); + break; + case Instruction::TIMESTAMP: + m_stack.push_back(_ext.currentBlock.timestamp); + break; + case Instruction::NUMBER: + m_stack.push_back(_ext.currentBlock.number); + break; + case Instruction::DIFFICULTY: + m_stack.push_back(_ext.currentBlock.difficulty); + break; + case Instruction::GASLIMIT: + m_stack.push_back(1000000); + break; + 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: + { + int i = (int)inst - (int)Instruction::PUSH1 + 1; + nextPC = m_curPC + 1; + m_stack.push_back(0); + for (; i--; nextPC++) + m_stack.back() = (m_stack.back() << 8) | _ext.getCode(nextPC); + break; + } + case Instruction::POP: + m_stack.pop_back(); + 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: + { + auto n = 1 + (int)inst - (int)Instruction::DUP1; + m_stack.push_back(m_stack[m_stack.size() - n]); + 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: + { + unsigned n = (int)inst - (int)Instruction::SWAP1 + 2; + auto d = m_stack.back(); + m_stack.back() = m_stack[m_stack.size() - n]; + m_stack[m_stack.size() - n] = d; + break; + } + case Instruction::MLOAD: + { + m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back()); + break; + } + case Instruction::MSTORE: + { + *(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + m_stack.pop_back(); + break; + } + case Instruction::MSTORE8: + { + m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff); + m_stack.pop_back(); + m_stack.pop_back(); + break; + } + case Instruction::SLOAD: + m_stack.back() = _ext.store(m_stack.back()); + break; + case Instruction::SSTORE: + _ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::JUMP: + nextPC = m_stack.back(); + if (!m_jumpDests.count(nextPC)) + BOOST_THROW_EXCEPTION(BadJumpDestination()); + m_stack.pop_back(); + break; + case Instruction::JUMPI: + if (m_stack[m_stack.size() - 2]) + { + nextPC = m_stack.back(); + if (!m_jumpDests.count(nextPC)) + BOOST_THROW_EXCEPTION(BadJumpDestination()); + } + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::PC: + m_stack.push_back(m_curPC); + break; + case Instruction::MSIZE: + m_stack.push_back(m_temp.size()); + break; + case Instruction::GAS: + m_stack.push_back(m_gas); + break; + case Instruction::JUMPDEST: + break; +/* case Instruction::LOG0: + _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + break; + case Instruction::LOG1: + _ext.log({m_stack[m_stack.size() - 1]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 2], (unsigned)m_stack[m_stack.size() - 3])); + break; + case Instruction::LOG2: + _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 3], (unsigned)m_stack[m_stack.size() - 4])); + break; + case Instruction::LOG3: + _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 4], (unsigned)m_stack[m_stack.size() - 5])); + break; + case Instruction::LOG4: + _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6])); + break;*/ + case Instruction::LOG0: + _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::LOG1: + _ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::LOG2: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::LOG3: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::LOG4: + _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + m_stack.pop_back(); + break; + case Instruction::CREATE: + { + u256 endowment = m_stack.back(); + m_stack.pop_back(); + unsigned initOff = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned initSize = (unsigned)m_stack.back(); + m_stack.pop_back(); + + if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024) + { + _ext.subBalance(endowment); + m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); + } + else + m_stack.push_back(0); + break; + } + case Instruction::CALL: + case Instruction::CALLCODE: + { + u256 gas = m_stack.back(); + m_stack.pop_back(); + Address receiveAddress = asAddress(m_stack.back()); + m_stack.pop_back(); + u256 value = m_stack.back(); + m_stack.pop_back(); + + unsigned inOff = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned inSize = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned outOff = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned outSize = (unsigned)m_stack.back(); + m_stack.pop_back(); + + if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024) + { + _ext.subBalance(value); + m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); + } + else + m_stack.push_back(0); + + m_gas += gas; + break; + } + case Instruction::RETURN: + { + unsigned b = (unsigned)m_stack.back(); + m_stack.pop_back(); + unsigned s = (unsigned)m_stack.back(); + m_stack.pop_back(); + + return bytesConstRef(m_temp.data() + b, s); + } + case Instruction::SUICIDE: + { + Address dest = asAddress(m_stack.back()); + _ext.suicide(dest); + // ...follow through to... + } + case Instruction::STOP: + return bytesConstRef(); + } + } + if (_steps == (uint64_t)-1) + BOOST_THROW_EXCEPTION(StepsDone()); + return bytesConstRef(); +} diff --git a/libevm/VM.h b/libevm/VM.h index 377effe11..ecf5de292 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -77,766 +77,5 @@ private: std::function m_onFail; }; -// TODO: Move it to cpp file. Not done to make review easier. -inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) -{ - auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; - - if (m_jumpDests.empty()) - for (unsigned i = 0; i < _ext.code.size(); ++i) - if (_ext.code[i] == (byte)Instruction::JUMPDEST) - m_jumpDests.insert(i); - 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; - auto osteps = _steps; - for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1) - { - // INSTRUCTION... - Instruction inst = (Instruction)_ext.getCode(m_curPC); - - // FEES... - bigint runGas = c_stepGas; - bigint newTempSize = m_temp.size(); - bigint copySize = 0; - - auto onOperation = [&]() - { - if (_onOp) - _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(onOperation); - - switch (inst) - { - case Instruction::STOP: - runGas = 0; - break; - - case Instruction::SUICIDE: - require(1); - runGas = 0; - break; - - case Instruction::SSTORE: - require(2); - 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 = 0; - _ext.sub.refunds += c_sstoreRefundGas; - } - else - runGas = c_sstoreResetGas; - break; - - case Instruction::SLOAD: - require(1); - runGas = c_sloadGas; - break; - - // These all operate on memory and therefore potentially expand it: - case Instruction::MSTORE: - require(2); - newTempSize = (bigint)m_stack.back() + 32; - break; - case Instruction::MSTORE8: - require(2); - newTempSize = (bigint)m_stack.back() + 1; - break; - case Instruction::MLOAD: - require(1); - newTempSize = (bigint)m_stack.back() + 32; - break; - case Instruction::RETURN: - require(2); - newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); - break; - case Instruction::SHA3: - require(2); - 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: - require(3); - copySize = m_stack[m_stack.size() - 3]; - newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); - break; - case Instruction::CODECOPY: - require(3); - copySize = m_stack[m_stack.size() - 3]; - newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); - break; - case Instruction::EXTCODECOPY: - require(4); - copySize = m_stack[m_stack.size() - 4]; - newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); - break; - - case Instruction::BALANCE: - require(1); - runGas = c_balanceGas; - break; - case Instruction::LOG0: - case Instruction::LOG1: - case Instruction::LOG2: - case Instruction::LOG3: - case Instruction::LOG4: - { - 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]; - newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]); - break; - } - - case Instruction::CALL: - case Instruction::CALLCODE: - require(7); - runGas = (bigint)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::CREATE: - { - require(3); - newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]); - runGas = c_createGas; - break; - } - case Instruction::EXP: - { - require(2); - auto expon = m_stack[m_stack.size() - 2]; - runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8)); - break; - } - - 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; - if (newTempSize > m_temp.size()) - runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32; - runGas += c_copyGas * (copySize + 31) / 32; - - onOperation(); -// if (_onOp) -// _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext); - - if (m_gas < runGas) - { - // Out of gas! - m_gas = 0; - BOOST_THROW_EXCEPTION(OutOfGas()); - } - - m_gas = (u256)((bigint)m_gas - runGas); - - if (newTempSize > m_temp.size()) - m_temp.resize((size_t)newTempSize); - - // EXECUTE... - switch (inst) - { - case Instruction::ADD: - //pops two items and pushes S[-1] + S[-2] mod 2^256. - m_stack[m_stack.size() - 2] += m_stack.back(); - m_stack.pop_back(); - break; - case Instruction::MUL: - //pops two items and pushes S[-1] * S[-2] mod 2^256. - m_stack[m_stack.size() - 2] *= m_stack.back(); - m_stack.pop_back(); - break; - case Instruction::SUB: - m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - break; - case Instruction::DIV: - 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(); - break; - case Instruction::SDIV: - 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(); - break; - case Instruction::MOD: - 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(); - break; - case Instruction::SMOD: - 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(); - break; - case Instruction::EXP: - { - auto base = m_stack.back(); - auto expon = m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256); - break; - } - case Instruction::NOT: - m_stack.back() = ~m_stack.back(); - break; - case Instruction::LT: - m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0; - m_stack.pop_back(); - break; - case Instruction::GT: - m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0; - m_stack.pop_back(); - break; - case Instruction::SLT: - m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; - m_stack.pop_back(); - break; - case Instruction::SGT: - m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0; - m_stack.pop_back(); - break; - case Instruction::EQ: - m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0; - m_stack.pop_back(); - break; - case Instruction::ISZERO: - m_stack.back() = m_stack.back() ? 0 : 1; - break; - case Instruction::AND: - m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - break; - case Instruction::OR: - m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - break; - case Instruction::XOR: - m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - break; - case Instruction::BYTE: - 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(); - break; - case Instruction::ADDMOD: - 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(); - break; - case Instruction::MULMOD: - 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(); - break; - case Instruction::SIGNEXTEND: - if (m_stack.back() < 31) - { - unsigned const testBit(m_stack.back() * 8 + 7); - u256& number = m_stack[m_stack.size() - 2]; - u256 mask = ((u256(1) << testBit) - 1); - if (boost::multiprecision::bit_test(number, testBit)) - number |= ~mask; - else - number &= mask; - } - m_stack.pop_back(); - break; - case Instruction::SHA3: - { - unsigned inOff = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned inSize = (unsigned)m_stack.back(); - m_stack.pop_back(); - m_stack.push_back(sha3(bytesConstRef(m_temp.data() + inOff, inSize))); - break; - } - case Instruction::ADDRESS: - m_stack.push_back(fromAddress(_ext.myAddress)); - break; - case Instruction::ORIGIN: - m_stack.push_back(fromAddress(_ext.origin)); - break; - case Instruction::BALANCE: - { - m_stack.back() = _ext.balance(asAddress(m_stack.back())); - break; - } - case Instruction::CALLER: - m_stack.push_back(fromAddress(_ext.caller)); - break; - case Instruction::CALLVALUE: - m_stack.push_back(_ext.value); - break; - case Instruction::CALLDATALOAD: - { - if ((unsigned)m_stack.back() + (uint64_t)31 < _ext.data.size()) - m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back()); - else - { - h256 r; - for (uint64_t i = (unsigned)m_stack.back(), e = (unsigned)m_stack.back() + (uint64_t)32, j = 0; i < e; ++i, ++j) - r[j] = i < _ext.data.size() ? _ext.data[i] : 0; - m_stack.back() = (u256)r; - } - break; - } - case Instruction::CALLDATASIZE: - m_stack.push_back(_ext.data.size()); - break; - case Instruction::CODESIZE: - m_stack.push_back(_ext.code.size()); - break; - case Instruction::EXTCODESIZE: - m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size(); - break; - case Instruction::CALLDATACOPY: - case Instruction::CODECOPY: - case Instruction::EXTCODECOPY: - { - Address a; - if (inst == Instruction::EXTCODECOPY) - { - a = asAddress(m_stack.back()); - m_stack.pop_back(); - } - unsigned offset = (unsigned)m_stack.back(); - m_stack.pop_back(); - u256 index = m_stack.back(); - m_stack.pop_back(); - unsigned size = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned sizeToBeCopied; - switch(inst) - { - case Instruction::CALLDATACOPY: - sizeToBeCopied = index + (bigint)size > (u256)_ext.data.size() ? (u256)_ext.data.size() < index ? 0 : _ext.data.size() - (unsigned)index : size; - memcpy(m_temp.data() + offset, _ext.data.data() + (unsigned)index, sizeToBeCopied); - break; - case Instruction::CODECOPY: - sizeToBeCopied = index + (bigint)size > (u256)_ext.code.size() ? (u256)_ext.code.size() < index ? 0 : _ext.code.size() - (unsigned)index : size; - memcpy(m_temp.data() + offset, _ext.code.data() + (unsigned)index, sizeToBeCopied); - break; - case Instruction::EXTCODECOPY: - sizeToBeCopied = index + (bigint)size > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < index ? 0 : _ext.codeAt(a).size() - (unsigned)index : size; - memcpy(m_temp.data() + offset, _ext.codeAt(a).data() + (unsigned)index, sizeToBeCopied); - break; - default: - // this is unreachable, but if someone introduces a bug in the future, he may get here. - assert(false); - BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested.")); - break; - } - memset(m_temp.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied); - break; - } - case Instruction::GASPRICE: - m_stack.push_back(_ext.gasPrice); - break; - case Instruction::BLOCKHASH: - m_stack.back() = (u256)_ext.blockhash(m_stack.back()); - break; - case Instruction::COINBASE: - m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); - break; - case Instruction::TIMESTAMP: - m_stack.push_back(_ext.currentBlock.timestamp); - break; - case Instruction::NUMBER: - m_stack.push_back(_ext.currentBlock.number); - break; - case Instruction::DIFFICULTY: - m_stack.push_back(_ext.currentBlock.difficulty); - break; - case Instruction::GASLIMIT: - m_stack.push_back(1000000); - break; - 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: - { - int i = (int)inst - (int)Instruction::PUSH1 + 1; - nextPC = m_curPC + 1; - m_stack.push_back(0); - for (; i--; nextPC++) - m_stack.back() = (m_stack.back() << 8) | _ext.getCode(nextPC); - break; - } - case Instruction::POP: - m_stack.pop_back(); - 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: - { - auto n = 1 + (int)inst - (int)Instruction::DUP1; - m_stack.push_back(m_stack[m_stack.size() - n]); - 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: - { - unsigned n = (int)inst - (int)Instruction::SWAP1 + 2; - auto d = m_stack.back(); - m_stack.back() = m_stack[m_stack.size() - n]; - m_stack[m_stack.size() - n] = d; - break; - } - case Instruction::MLOAD: - { - m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back()); - break; - } - case Instruction::MSTORE: - { - *(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2]; - m_stack.pop_back(); - m_stack.pop_back(); - break; - } - case Instruction::MSTORE8: - { - m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff); - m_stack.pop_back(); - m_stack.pop_back(); - break; - } - case Instruction::SLOAD: - m_stack.back() = _ext.store(m_stack.back()); - break; - case Instruction::SSTORE: - _ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::JUMP: - nextPC = m_stack.back(); - if (!m_jumpDests.count(nextPC)) - BOOST_THROW_EXCEPTION(BadJumpDestination()); - m_stack.pop_back(); - break; - case Instruction::JUMPI: - if (m_stack[m_stack.size() - 2]) - { - nextPC = m_stack.back(); - if (!m_jumpDests.count(nextPC)) - BOOST_THROW_EXCEPTION(BadJumpDestination()); - } - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::PC: - m_stack.push_back(m_curPC); - break; - case Instruction::MSIZE: - m_stack.push_back(m_temp.size()); - break; - case Instruction::GAS: - m_stack.push_back(m_gas); - break; - case Instruction::JUMPDEST: - break; -/* case Instruction::LOG0: - _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - break; - case Instruction::LOG1: - _ext.log({m_stack[m_stack.size() - 1]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 2], (unsigned)m_stack[m_stack.size() - 3])); - break; - case Instruction::LOG2: - _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 3], (unsigned)m_stack[m_stack.size() - 4])); - break; - case Instruction::LOG3: - _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 4], (unsigned)m_stack[m_stack.size() - 5])); - break; - case Instruction::LOG4: - _ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6])); - break;*/ - case Instruction::LOG0: - _ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::LOG1: - _ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::LOG2: - _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::LOG3: - _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::LOG4: - _ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2])); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - m_stack.pop_back(); - break; - case Instruction::CREATE: - { - u256 endowment = m_stack.back(); - m_stack.pop_back(); - unsigned initOff = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned initSize = (unsigned)m_stack.back(); - m_stack.pop_back(); - - if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024) - { - _ext.subBalance(endowment); - m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); - } - else - m_stack.push_back(0); - break; - } - case Instruction::CALL: - case Instruction::CALLCODE: - { - u256 gas = m_stack.back(); - m_stack.pop_back(); - Address receiveAddress = asAddress(m_stack.back()); - m_stack.pop_back(); - u256 value = m_stack.back(); - m_stack.pop_back(); - - unsigned inOff = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned inSize = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned outOff = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned outSize = (unsigned)m_stack.back(); - m_stack.pop_back(); - - if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024) - { - _ext.subBalance(value); - m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); - } - else - m_stack.push_back(0); - - m_gas += gas; - break; - } - case Instruction::RETURN: - { - unsigned b = (unsigned)m_stack.back(); - m_stack.pop_back(); - unsigned s = (unsigned)m_stack.back(); - m_stack.pop_back(); - - return bytesConstRef(m_temp.data() + b, s); - } - case Instruction::SUICIDE: - { - Address dest = asAddress(m_stack.back()); - _ext.suicide(dest); - // ...follow through to... - } - case Instruction::STOP: - return bytesConstRef(); - } - } - if (_steps == (uint64_t)-1) - BOOST_THROW_EXCEPTION(StepsDone()); - return bytesConstRef(); -} - } }