From 94df0ea77f01f31fa458a147a7be1badaffe9afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 16:27:35 +0100 Subject: [PATCH 1/8] Introducing VMFace - common VM interface --- libevm/VM.cpp | 42 ++++++++++++-------- libevm/VM.h | 36 +++++++---------- libevm/VMFace.h | 61 +++++++++++++++++++++++++++++ windows/LibEthereum.vcxproj | 3 +- windows/LibEthereum.vcxproj.filters | 11 +++--- 5 files changed, 107 insertions(+), 46 deletions(-) create mode 100644 libevm/VMFace.h diff --git a/libevm/VM.cpp b/libevm/VM.cpp index bded9a10d..996e51eea 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -1,33 +1,41 @@ /* - This file is part of cpp-ethereum. +This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +cpp-ethereum is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +cpp-ethereum is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . +You should have received a copy of the GNU General Public License +along with cpp-ethereum. If not, see . */ /** @file VM.cpp - * @author Gav Wood - * @date 2014 - */ +* @author Gav Wood +* @date 2014 +*/ #include "VM.h" +#include -using namespace std; using namespace dev; using namespace dev::eth; -void VM::reset(u256 _gas) +void VM::reset(u256 _gas) noexcept { - m_gas = _gas; + VMFace::reset(_gas); m_curPC = 0; m_jumpDests.clear(); } + +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) +{ + if (auto defaultExt = dynamic_cast(&_ext)) + return goImpl(*defaultExt, _onOp, _steps); + else + return goImpl(_ext, _onOp, _steps); +} diff --git a/libevm/VM.h b/libevm/VM.h index 5fb46fc68..bb34bceb2 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -28,21 +28,13 @@ #include #include #include "FeeStructure.h" -#include "ExtVMFace.h" +#include "VMFace.h" namespace dev { namespace eth { -struct VMException: virtual Exception {}; -struct StepsDone: virtual VMException {}; -struct BreakPointHit: virtual VMException {}; -struct BadInstruction: virtual VMException {}; -struct BadJumpDestination: virtual VMException {}; -struct OutOfGas: virtual VMException {}; -struct StackTooSmall: virtual public VMException {}; - // Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. // Currently we just pull out the right (low-order in BE) 160-bits. inline Address asAddress(u256 _item) @@ -57,28 +49,28 @@ inline u256 fromAddress(Address _a) /** */ -class VM +class VM : public VMFace { public: /// Construct VM object. - explicit VM(u256 _gas = 0) { reset(_gas); } + explicit VM(u256 _gas = 0) : VMFace(_gas) {} - void reset(u256 _gas = 0); + virtual void reset(u256 _gas = 0) noexcept override final; - template - bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; void require(u256 _n) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError((bigint)_n, (bigint)m_stack.size())); } } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } - u256 gas() const { return m_gas; } u256 curPC() const { return m_curPC; } bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } private: - u256 m_gas = 0; + template + bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); + u256 m_curPC = 0; bytes m_temp; u256s m_stack; @@ -89,7 +81,7 @@ private: } // INLINE: -template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps) +template dev::bytesConstRef dev::eth::VM::goImpl(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps) { auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; @@ -164,7 +156,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con case Instruction::SLOAD: require(1); - runGas = c_sloadGas; + runGas = c_sloadGas; break; // These all operate on memory and therefore potentially expand it: @@ -412,7 +404,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con 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[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: @@ -420,7 +412,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con 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[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: @@ -443,11 +435,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con 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[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[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: diff --git a/libevm/VMFace.h b/libevm/VMFace.h new file mode 100644 index 000000000..f6db7d0b5 --- /dev/null +++ b/libevm/VMFace.h @@ -0,0 +1,61 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#pragma once + +#include +#include +#include "ExtVMFace.h" + +namespace dev +{ +namespace eth +{ + +struct VMException : virtual Exception {}; +struct StepsDone : virtual VMException {}; +struct BreakPointHit : virtual VMException {}; +struct BadInstruction : virtual VMException {}; +struct BadJumpDestination : virtual VMException {}; +struct OutOfGas : virtual VMException {}; +struct StackTooSmall : virtual public VMException {}; + +/** + */ +class VMFace +{ +public: + /// Construct VM object. + explicit VMFace(u256 _gas = 0): m_gas(_gas) {} + + virtual ~VMFace() = default; + + VMFace(VMFace const&) = delete; + void operator=(VMFace const&) = delete; + + virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } + + virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; + + u256 gas() const { return m_gas; } + +protected: + u256 m_gas = 0; +}; + +} +} diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 06f868023..cbacd51b5 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -368,6 +368,7 @@ true true + @@ -568,4 +569,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 114364008..76201d823 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -190,18 +190,14 @@ libdevcrypto - - libdevcrypto - - - libdevcrypto - libethereum libevmcore + + @@ -438,6 +434,9 @@ libevmcore + + libevm + From 160aa47288a2dfb71706ef91eb5cefd72448e7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 5 Dec 2014 17:00:29 +0100 Subject: [PATCH 2/8] Use safe pointers in Executive --- libethereum/Executive.cpp | 15 ++++----------- libethereum/Executive.h | 17 +++++++++-------- libethereum/State.cpp | 1 + libethereum/State.h | 1 - test/vm.cpp | 1 + 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 6a123875c..db77d349a 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -32,13 +32,6 @@ using namespace dev::eth; #define ETH_VMTRACE 1 -Executive::~Executive() -{ - // TODO: Make safe. - delete m_ext; - delete m_vm; -} - u256 Executive::gasUsed() const { return m_t.gas() - m_endGas; @@ -112,9 +105,9 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu if (m_s.addressHasCode(_receiveAddress)) { - m_vm = new VM(_gas); + m_vm.reset(new VM(_gas)); bytes const& c = m_s.code(_receiveAddress); - m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms); + m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms)); } else m_endGas = _gas; @@ -131,8 +124,8 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. - m_vm = new VM(_gas); - m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms); + m_vm.reset(new VM(_gas)); + m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms)); return _init.empty(); } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 930c2859b..f2ee6a77d 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -25,18 +25,17 @@ #include #include #include -#include +#include #include "Transaction.h" -#include "Manifest.h" +#include "ExtVM.h" namespace dev { namespace eth { -class VM; -class ExtVM; class State; +struct Manifest; struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; }; @@ -44,7 +43,9 @@ class Executive { public: Executive(State& _s, Manifest* o_ms = nullptr): m_s(_s), m_ms(o_ms) {} - ~Executive(); + ~Executive() = default; + Executive(Executive const&) = delete; + void operator=(Executive) = delete; bool setup(bytesConstRef _transaction); bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); @@ -63,14 +64,14 @@ public: h160 newAddress() const { return m_newAddress; } LogEntries const& logs() const { return m_logs; } - VM const& vm() const { return *m_vm; } + VMFace const& vm() const { return *m_vm; } State const& state() const { return m_s; } ExtVM const& ext() const { return *m_ext; } private: State& m_s; - ExtVM* m_ext = nullptr; // TODO: make safe. - VM* m_vm = nullptr; + std::unique_ptr m_ext; + std::unique_ptr m_vm; Manifest* m_ms = nullptr; bytesConstRef m_out; Address m_newAddress; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 9a0426e18..335b7ff04 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -33,6 +33,7 @@ #include "BlockChain.h" #include "Defaults.h" #include "ExtVM.h" +#include "Executive.h" using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libethereum/State.h b/libethereum/State.h index 9c41843ff..5fcfa1cf7 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -36,7 +36,6 @@ #include "Account.h" #include "Transaction.h" #include "TransactionReceipt.h" -#include "Executive.h" #include "AccountDiff.h" namespace dev diff --git a/test/vm.cpp b/test/vm.cpp index d7bc0612a..67102dcd2 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -21,6 +21,7 @@ */ #include +#include #include "vm.h" using namespace std; From debc585fc553b4ffbd40fcf775721282380d9679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 9 Dec 2014 14:11:45 +0100 Subject: [PATCH 3/8] Revert unnecessary whitespace changes --- libevm/VM.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 996e51eea..44620a3d5 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -1,23 +1,23 @@ /* -This file is part of cpp-ethereum. + This file is part of cpp-ethereum. -cpp-ethereum is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -cpp-ethereum is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with cpp-ethereum. If not, see . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file VM.cpp -* @author Gav Wood -* @date 2014 -*/ + * @author Gav Wood + * @date 2014 + */ #include "VM.h" #include From 4261a7159d0c130ea976742fe616d601c43f3b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 9 Dec 2014 15:28:31 +0100 Subject: [PATCH 4/8] Fix alethzero build --- alethzero/MainWin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 50b9df413..fffc5843f 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include From b1dc0d5e6a1093bcb8849d932df7c7a91578f1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Dec 2014 17:41:53 +0100 Subject: [PATCH 5/8] VMFactory - a new way of creating VMs --- libethereum/Executive.cpp | 5 +++-- libethereum/State.cpp | 14 ++++++------ libevm/ExtVMFace.h | 2 +- libevm/VM.h | 8 ++++--- libevm/VMFactory.cpp | 46 +++++++++++++++++++++++++++++++++++++++ libevm/VMFactory.h | 43 ++++++++++++++++++++++++++++++++++++ test/createRandomTest.cpp | 8 +++---- test/vm.cpp | 7 +++--- 8 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 libevm/VMFactory.cpp create mode 100644 libevm/VMFactory.h diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index db77d349a..9e2f5ee07 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "Interface.h" #include "Executive.h" @@ -105,7 +106,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu if (m_s.addressHasCode(_receiveAddress)) { - m_vm.reset(new VM(_gas)); + m_vm = VMFactory::create(_gas); bytes const& c = m_s.code(_receiveAddress); m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms)); } @@ -124,7 +125,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. - m_vm.reset(new VM(_gas)); + m_vm = VMFactory::create(_gas); m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms)); return _init.empty(); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 335b7ff04..feb732882 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "BlockChain.h" #include "Defaults.h" #include "ExtVM.h" @@ -1214,19 +1214,19 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } else if (addressHasCode(_codeAddress)) { - VM vm(*_gas); + auto vm = VMFactory::create(*_gas); ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; try { - auto out = vm.go(evm, _onOp); + auto out = vm->go(evm, _onOp); memcpy(_out.data(), out.data(), std::min(out.size(), _out.size())); if (o_sub) *o_sub += evm.sub; if (o_ms) o_ms->output = out.toBytes(); - *_gas = vm.gas(); + *_gas = vm->gas(); } catch (VMException const& _e) { @@ -1273,19 +1273,19 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. - VM vm(*_gas); + auto vm = VMFactory::create(*_gas); ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; try { - out = vm.go(evm, _onOp); + out = vm->go(evm, _onOp); if (o_ms) o_ms->output = out.toBytes(); if (o_sub) *o_sub += evm.sub; - *_gas = vm.gas(); + *_gas = vm->gas(); } catch (VMException const& _e) { diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 4a175ff4e..52798cd89 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -150,7 +150,7 @@ public: BlockInfo previousBlock; ///< The previous block's information. BlockInfo currentBlock; ///< The current block's information. SubState sub; ///< Sub-band VM state (suicides, refund counter, logs). - unsigned depth; ///< Depth of the present call. + unsigned depth = 0; ///< Depth of the present call. }; } diff --git a/libevm/VM.h b/libevm/VM.h index 654e9719f..3b9e32c7b 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -52,9 +52,6 @@ inline u256 fromAddress(Address _a) class VM : public VMFace { public: - /// Construct VM object. - explicit VM(u256 _gas = 0) : VMFace(_gas) {} - virtual void reset(u256 _gas = 0) noexcept override final; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; @@ -68,6 +65,11 @@ public: u256s const& stack() const { return m_stack; } private: + friend class VMFactory; + + /// Construct VM object. + explicit VM(u256 _gas = 0) : VMFace(_gas) {} + template bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); diff --git a/libevm/VMFactory.cpp b/libevm/VMFactory.cpp new file mode 100644 index 000000000..423c6b8ce --- /dev/null +++ b/libevm/VMFactory.cpp @@ -0,0 +1,46 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#include "VMFactory.h" +#include +#include "VM.h" + +namespace dev +{ +namespace eth +{ +namespace +{ + VMKind g_kind = VMKind::Interpreter; +} + +void VMFactory::setKind(VMKind _kind) +{ + g_kind = _kind; +} + +std::unique_ptr VMFactory::create(u256 _gas) +{ + assert(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); + return std::unique_ptr(new VM(_gas)); +} + +} +} + + + diff --git a/libevm/VMFactory.h b/libevm/VMFactory.h new file mode 100644 index 000000000..155350602 --- /dev/null +++ b/libevm/VMFactory.h @@ -0,0 +1,43 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#include "VMFace.h" + +namespace dev +{ +namespace eth +{ + +enum class VMKind : bool +{ + Interpreter, + JIT +}; + +class VMFactory +{ +public: + VMFactory() = delete; + + static std::unique_ptr create(u256 _gas); + + static void setKind(VMKind _kind); + +}; + +} +} diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index caeeb6b67..a11688457 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "vm.h" using namespace std; @@ -142,14 +142,14 @@ void doMyTests(json_spirit::mValue& v) } bytes output; - eth::VM vm(fev.gas); + auto vm = eth::VMFactory::create(fev.gas); u256 gas; bool vmExceptionOccured = false; try { - output = vm.go(fev, fev.simpleTrace()).toBytes(); - gas = vm.gas(); + output = vm->go(fev, fev.simpleTrace()).toBytes(); + gas = vm->gas(); } catch (eth::VMException const& _e) { diff --git a/test/vm.cpp b/test/vm.cpp index 45034b716..02cee0a05 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "vm.h" using namespace std; @@ -298,14 +299,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } bytes output; - VM vm(fev.gas); + auto vm = eth::VMFactory::create(fev.gas); u256 gas; bool vmExceptionOccured = false; try { - output = vm.go(fev, fev.simpleTrace()).toBytes(); - gas = vm.gas(); + output = vm->go(fev, fev.simpleTrace()).toBytes(); + gas = vm->gas(); } catch (VMException const& _e) { From c7526d0d95a3eff32494f572b2b2a1dee24bdf98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Dec 2014 20:13:33 +0100 Subject: [PATCH 6/8] Style fixes (mostly) --- libevm/VM.h | 4 ++-- libevm/VMFace.h | 14 +++++++------- libevm/VMFactory.cpp | 3 +-- libevm/VMFactory.h | 3 ++- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index 3b9e32c7b..d03760a78 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -49,7 +49,7 @@ inline u256 fromAddress(Address _a) /** */ -class VM : public VMFace +class VM: public VMFace { public: virtual void reset(u256 _gas = 0) noexcept override final; @@ -68,7 +68,7 @@ private: friend class VMFactory; /// Construct VM object. - explicit VM(u256 _gas = 0) : VMFace(_gas) {} + explicit VM(u256 _gas = 0): VMFace(_gas) {} template bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); diff --git a/libevm/VMFace.h b/libevm/VMFace.h index f6db7d0b5..319da7fc1 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -26,13 +26,13 @@ namespace dev namespace eth { -struct VMException : virtual Exception {}; -struct StepsDone : virtual VMException {}; -struct BreakPointHit : virtual VMException {}; -struct BadInstruction : virtual VMException {}; -struct BadJumpDestination : virtual VMException {}; -struct OutOfGas : virtual VMException {}; -struct StackTooSmall : virtual public VMException {}; +struct VMException: virtual Exception {}; +struct StepsDone: virtual VMException {}; +struct BreakPointHit: virtual VMException {}; +struct BadInstruction: virtual VMException {}; +struct BadJumpDestination: virtual VMException {}; +struct OutOfGas: virtual VMException {}; +struct StackTooSmall: virtual VMException {}; /** */ diff --git a/libevm/VMFactory.cpp b/libevm/VMFactory.cpp index 423c6b8ce..90e17c553 100644 --- a/libevm/VMFactory.cpp +++ b/libevm/VMFactory.cpp @@ -16,7 +16,6 @@ */ #include "VMFactory.h" -#include #include "VM.h" namespace dev @@ -35,7 +34,7 @@ void VMFactory::setKind(VMKind _kind) std::unique_ptr VMFactory::create(u256 _gas) { - assert(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); + asserts(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); return std::unique_ptr(new VM(_gas)); } diff --git a/libevm/VMFactory.h b/libevm/VMFactory.h index 155350602..c5d9c4f65 100644 --- a/libevm/VMFactory.h +++ b/libevm/VMFactory.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ +#pragma once #include "VMFace.h" @@ -22,7 +23,7 @@ namespace dev namespace eth { -enum class VMKind : bool +enum class VMKind: bool { Interpreter, JIT From 15b2fcd5432492ec4d4a6e36f492db3d824ed1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Dec 2014 21:55:29 +0100 Subject: [PATCH 7/8] Catch exception by reference --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index feb732882..539cb55f0 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1102,7 +1102,7 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const return false; } } - catch (InvalidTrie) + catch (InvalidTrie const&) { cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]"; cnote << m_db.keys(); From 7e2e58aaa5793620a7f2e0860e811c86861bb1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 11 Dec 2014 15:41:19 +0100 Subject: [PATCH 8/8] VM::go detemplatized. Cleanups. --- libevm/VM.cpp | 8 -------- libevm/VM.h | 13 +++++-------- libevm/VMFace.h | 12 +++--------- libevm/VMFactory.cpp | 3 --- libevm/VMFactory.h | 2 -- 5 files changed, 8 insertions(+), 30 deletions(-) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 44620a3d5..b8452e4f5 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -31,11 +31,3 @@ void VM::reset(u256 _gas) noexcept m_curPC = 0; m_jumpDests.clear(); } - -bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) -{ - if (auto defaultExt = dynamic_cast(&_ext)) - return goImpl(*defaultExt, _onOp, _steps); - else - return goImpl(_ext, _onOp, _steps); -} diff --git a/libevm/VM.h b/libevm/VM.h index d03760a78..c427802f6 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -68,10 +68,7 @@ private: friend class VMFactory; /// Construct VM object. - explicit VM(u256 _gas = 0): VMFace(_gas) {} - - template - bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); + explicit VM(u256 _gas): VMFace(_gas) {} u256 m_curPC = 0; bytes m_temp; @@ -80,10 +77,8 @@ private: std::function m_onFail; }; -} - -// INLINE: -template dev::bytesConstRef dev::eth::VM::goImpl(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps) +// 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; }; @@ -864,4 +859,6 @@ template dev::bytesConstRef dev::eth::VM::goImpl(Ext& _ext, OnOpFunc BOOST_THROW_EXCEPTION(StepsDone()); return bytesConstRef(); } + +} } diff --git a/libevm/VMFace.h b/libevm/VMFace.h index 319da7fc1..44ae03868 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -14,7 +14,6 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ - #pragma once #include @@ -34,25 +33,20 @@ struct BadJumpDestination: virtual VMException {}; struct OutOfGas: virtual VMException {}; struct StackTooSmall: virtual VMException {}; -/** - */ +/// EVM Virtual Machine interface class VMFace { public: - /// Construct VM object. - explicit VMFace(u256 _gas = 0): m_gas(_gas) {} - + explicit VMFace(u256 _gas): m_gas(_gas) {} virtual ~VMFace() = default; - VMFace(VMFace const&) = delete; void operator=(VMFace const&) = delete; virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } + u256 gas() const noexcept { return m_gas; } virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; - u256 gas() const { return m_gas; } - protected: u256 m_gas = 0; }; diff --git a/libevm/VMFactory.cpp b/libevm/VMFactory.cpp index 90e17c553..af37ec710 100644 --- a/libevm/VMFactory.cpp +++ b/libevm/VMFactory.cpp @@ -40,6 +40,3 @@ std::unique_ptr VMFactory::create(u256 _gas) } } - - - diff --git a/libevm/VMFactory.h b/libevm/VMFactory.h index c5d9c4f65..d0d02e0c4 100644 --- a/libevm/VMFactory.h +++ b/libevm/VMFactory.h @@ -35,9 +35,7 @@ public: VMFactory() = delete; static std::unique_ptr create(u256 _gas); - static void setKind(VMKind _kind); - }; }