Browse Source

Introducing VMFace - common VM interface

cl-refactor
Paweł Bylica 10 years ago
parent
commit
94df0ea77f
  1. 42
      libevm/VM.cpp
  2. 36
      libevm/VM.h
  3. 61
      libevm/VMFace.h
  4. 3
      windows/LibEthereum.vcxproj
  5. 11
      windows/LibEthereum.vcxproj.filters

42
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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file VM.cpp /** @file VM.cpp
* @author Gav Wood <i@gavwood.com> * @author Gav Wood <i@gavwood.com>
* @date 2014 * @date 2014
*/ */
#include "VM.h" #include "VM.h"
#include <libethereum/ExtVM.h>
using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; 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_curPC = 0;
m_jumpDests.clear(); m_jumpDests.clear();
} }
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
if (auto defaultExt = dynamic_cast<ExtVM*>(&_ext))
return goImpl<ExtVM>(*defaultExt, _onOp, _steps);
else
return goImpl<ExtVMFace>(_ext, _onOp, _steps);
}

36
libevm/VM.h

@ -28,21 +28,13 @@
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include "FeeStructure.h" #include "FeeStructure.h"
#include "ExtVMFace.h" #include "VMFace.h"
namespace dev namespace dev
{ {
namespace eth 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. // 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. // Currently we just pull out the right (low-order in BE) 160-bits.
inline Address asAddress(u256 _item) inline Address asAddress(u256 _item)
@ -57,28 +49,28 @@ inline u256 fromAddress(Address _a)
/** /**
*/ */
class VM class VM : public VMFace
{ {
public: public:
/// Construct VM object. /// 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 <class Ext> virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1);
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 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); } } 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; } u256 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:
u256 m_gas = 0; template <class Ext>
bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1);
u256 m_curPC = 0; u256 m_curPC = 0;
bytes m_temp; bytes m_temp;
u256s m_stack; u256s m_stack;
@ -89,7 +81,7 @@ private:
} }
// INLINE: // INLINE:
template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc const& _onOp, uint64_t _steps) template <class Ext> 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; }; auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
@ -164,7 +156,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
case Instruction::SLOAD: case Instruction::SLOAD:
require(1); require(1);
runGas = c_sloadGas; runGas = c_sloadGas;
break; break;
// These all operate on memory and therefore potentially expand it: // These all operate on memory and therefore potentially expand it:
@ -412,7 +404,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SDIV: 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(); m_stack.pop_back();
break; break;
case Instruction::MOD: case Instruction::MOD:
@ -420,7 +412,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SMOD: 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(); m_stack.pop_back();
break; break;
case Instruction::EXP: case Instruction::EXP:
@ -443,11 +435,11 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
m_stack.pop_back(); m_stack.pop_back();
break; break;
case Instruction::SLT: 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(); m_stack.pop_back();
break; break;
case Instruction::SGT: 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(); m_stack.pop_back();
break; break;
case Instruction::EQ: case Instruction::EQ:

61
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <memory>
#include <libdevcore/Exceptions.h>
#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;
};
}
}

3
windows/LibEthereum.vcxproj

@ -368,6 +368,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevm\VMFace.h" />
<ClInclude Include="..\liblll\All.h" /> <ClInclude Include="..\liblll\All.h" />
<ClInclude Include="..\liblll\CodeFragment.h" /> <ClInclude Include="..\liblll\CodeFragment.h" />
<ClInclude Include="..\liblll\Compiler.h" /> <ClInclude Include="..\liblll\Compiler.h" />
@ -568,4 +569,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

11
windows/LibEthereum.vcxproj.filters

@ -190,18 +190,14 @@
<ClCompile Include="..\libdevcrypto\CryptoPP.cpp"> <ClCompile Include="..\libdevcrypto\CryptoPP.cpp">
<Filter>libdevcrypto</Filter> <Filter>libdevcrypto</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libdevcrypto\EC.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
<ClCompile Include="..\libdevcrypto\SHA3MAC.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
<ClCompile Include="..\libethereum\Account.cpp"> <ClCompile Include="..\libethereum\Account.cpp">
<Filter>libethereum</Filter> <Filter>libethereum</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libevmcore\Assembly.cpp"> <ClCompile Include="..\libevmcore\Assembly.cpp">
<Filter>libevmcore</Filter> <Filter>libevmcore</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libdevcrypto\AES.cpp" />
<ClCompile Include="..\libdevcrypto\ECDHE.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@ -438,6 +434,9 @@
<ClInclude Include="..\libevmcore\Assembly.h"> <ClInclude Include="..\libevmcore\Assembly.h">
<Filter>libevmcore</Filter> <Filter>libevmcore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevm\VMFace.h">
<Filter>libevm</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Windows"> <Filter Include="Windows">

Loading…
Cancel
Save