Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
702947e6c5
  1. 1
      alethzero/MainWin.h
  2. 13
      libethereum/Executive.cpp
  3. 19
      libethereum/Executive.h
  4. 17
      libethereum/State.cpp
  5. 1
      libethereum/State.h
  6. 2
      libevm/ExtVMFace.h
  7. 6
      libevm/VM.cpp
  8. 45
      libevm/VM.h
  9. 55
      libevm/VMFace.h
  10. 42
      libevm/VMFactory.cpp
  11. 42
      libevm/VMFactory.h
  12. 8
      test/createRandomTest.cpp
  13. 8
      test/vm.cpp
  14. 3
      windows/LibEthereum.vcxproj
  15. 11
      windows/LibEthereum.vcxproj.filters

1
alethzero/MainWin.h

@ -33,6 +33,7 @@
#include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <libqethereum/QEthereum.h>
#include <libwebthree/WebThree.h>

13
libethereum/Executive.cpp

@ -21,6 +21,7 @@
#include <boost/timer.hpp>
#include <libdevcore/CommonIO.h>
#include <libevm/VMFactory.h>
#include <libevm/VM.h>
#include "Interface.h"
#include "Executive.h"
@ -32,10 +33,6 @@ using namespace dev::eth;
#define ETH_VMTRACE 1
Executive::~Executive()
{
}
u256 Executive::gasUsed() const
{
return m_t.gas() - m_endGas;
@ -114,9 +111,9 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
}
else if (m_s.addressHasCode(_receiveAddress))
{
m_vm = make_shared<VM>(_gas);
m_vm = VMFactory::create(_gas);
bytes const& c = m_s.code(_receiveAddress);
m_ext = make_shared<ExtVM>(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c);
m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c));
}
else
m_endGas = _gas;
@ -133,8 +130,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 = make_shared<VM>(_gas);
m_ext = make_shared<ExtVM>(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init);
m_vm = VMFactory::create(_gas);
m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init));
return _init.empty();
}

19
libethereum/Executive.h

@ -25,26 +25,27 @@
#include <libdevcore/Log.h>
#include <libevmcore/Instruction.h>
#include <libethcore/CommonEth.h>
#include <libevm/ExtVMFace.h>
#include <libevm/VMFace.h>
#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; };
class Executive
{
public:
Executive(State& _s): m_s(_s){}
~Executive();
Executive(State& _s): m_s(_s) {}
~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;
std::shared_ptr<ExtVM> m_ext;
std::shared_ptr<VM> m_vm;
std::unique_ptr<ExtVM> m_ext;
std::unique_ptr<VMFace> m_vm;
bytesConstRef m_out;
Address m_newAddress;

17
libethereum/State.cpp

@ -29,10 +29,11 @@
#include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h>
#include <libethcore/Exceptions.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include "BlockChain.h"
#include "Defaults.h"
#include "ExtVM.h"
#include "Executive.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -1093,7 +1094,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();
@ -1196,15 +1197,15 @@ 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), _level);
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;
*_gas = vm.gas();
*_gas = vm->gas();
// Write state out only in the case of a non-excepted transaction.
return true;
}
@ -1244,16 +1245,16 @@ 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, _level);
bytesConstRef out;
try
{
out = vm.go(evm, _onOp);
out = vm->go(evm, _onOp);
if (o_sub)
*o_sub += evm.sub;
*_gas = vm.gas();
*_gas = vm->gas();
if (out.size() * c_createDataGas <= *_gas)
*_gas -= out.size() * c_createDataGas;

1
libethereum/State.h

@ -36,7 +36,6 @@
#include "Account.h"
#include "Transaction.h"
#include "TransactionReceipt.h"
#include "Executive.h"
#include "AccountDiff.h"
namespace dev

2
libevm/ExtVMFace.h

@ -153,7 +153,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.
};
}

6
libevm/VM.cpp

@ -20,14 +20,14 @@
*/
#include "VM.h"
#include <libethereum/ExtVM.h>
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();
}

45
libevm/VM.h

@ -28,21 +28,13 @@
#include <libdevcrypto/SHA3.h>
#include <libethcore/BlockInfo.h>
#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,27 @@ inline u256 fromAddress(Address _a)
/**
*/
class VM
class VM: public VMFace
{
public:
/// Construct VM object.
explicit VM(u256 _gas = 0) { reset(_gas); }
void reset(u256 _gas = 0);
virtual void reset(u256 _gas = 0) noexcept override final;
template <class Ext>
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;
friend class VMFactory;
/// Construct VM object.
explicit VM(u256 _gas): VMFace(_gas) {}
u256 m_curPC = 0;
bytes m_temp;
u256s m_stack;
@ -86,10 +77,8 @@ private:
std::function<void()> m_onFail;
};
}
// INLINE:
template <class Ext> dev::bytesConstRef dev::eth::VM::go(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; };
@ -164,7 +153,7 @@ template <class Ext> 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 +401,7 @@ template <class Ext> 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 +409,7 @@ template <class Ext> 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 +432,11 @@ template <class Ext> 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:
@ -870,4 +859,6 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
BOOST_THROW_EXCEPTION(StepsDone());
return bytesConstRef();
}
}
}

55
libevm/VMFace.h

@ -0,0 +1,55 @@
/*
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 VMException {};
/// EVM Virtual Machine interface
class VMFace
{
public:
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;
protected:
u256 m_gas = 0;
};
}
}

42
libevm/VMFactory.cpp

@ -0,0 +1,42 @@
/*
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/>.
*/
#include "VMFactory.h"
#include "VM.h"
namespace dev
{
namespace eth
{
namespace
{
VMKind g_kind = VMKind::Interpreter;
}
void VMFactory::setKind(VMKind _kind)
{
g_kind = _kind;
}
std::unique_ptr<VMFace> VMFactory::create(u256 _gas)
{
asserts(g_kind == VMKind::Interpreter && "Only interpreter supported for now");
return std::unique_ptr<VMFace>(new VM(_gas));
}
}
}

42
libevm/VMFactory.h

@ -0,0 +1,42 @@
/*
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 "VMFace.h"
namespace dev
{
namespace eth
{
enum class VMKind: bool
{
Interpreter,
JIT
};
class VMFactory
{
public:
VMFactory() = delete;
static std::unique_ptr<VMFace> create(u256 _gas);
static void setKind(VMKind _kind);
};
}
}

8
test/createRandomTest.cpp

@ -32,7 +32,7 @@
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#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)
{

8
test/vm.cpp

@ -21,6 +21,8 @@
*/
#include <boost/filesystem.hpp>
#include <libethereum/Executive.h>
#include <libevm/VMFactory.h>
#include "vm.h"
using namespace std;
@ -298,14 +300,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)
{

3
windows/LibEthereum.vcxproj

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

11
windows/LibEthereum.vcxproj.filters

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

Loading…
Cancel
Save