Browse Source

Merge branch 'refactor' into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
7e47b4900e
  1. 4
      alethzero/MainWin.cpp
  2. 2
      eth/main.cpp
  3. 1
      libdevcore/vector_ref.h
  4. 62
      libethereum/Executive.cpp
  5. 20
      libethereum/Executive.h
  6. 10
      libethereum/ExtVM.h
  7. 153
      libethereum/State.cpp
  8. 6
      libethereum/State.h
  9. 11
      libevm/ExtVMFace.h
  10. 4
      libevm/VM.h
  11. 4
      test/solidityExecutionFramework.h
  12. 2
      test/state.cpp
  13. 3
      test/trie.cpp
  14. 8
      test/vm.cpp
  15. 4
      test/vm.h
  16. 5
      test/whisperTopic.cpp

4
alethzero/MainWin.cpp

@ -1350,7 +1350,7 @@ void Main::on_debugCurrent_triggered()
{ {
unsigned txi = item->data(Qt::UserRole + 1).toInt(); unsigned txi = item->data(Qt::UserRole + 1).toInt();
m_executiveState = ethereum()->state(txi + 1, h); m_executiveState = ethereum()->state(txi + 1, h);
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState)); m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState, 0));
Transaction t = m_executiveState.pending()[txi]; Transaction t = m_executiveState.pending()[txi];
m_executiveState = m_executiveState.fromPending(txi); m_executiveState = m_executiveState.fromPending(txi);
auto r = t.rlp(); auto r = t.rlp();
@ -1855,7 +1855,7 @@ void Main::on_debug_clicked()
{ {
Secret s = i.secret(); Secret s = i.secret();
m_executiveState = ethereum()->postState(); m_executiveState = ethereum()->postState();
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState)); m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState, 0));
Transaction t = isCreation() ? Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) : Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s); Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s);

2
eth/main.cpp

@ -620,7 +620,7 @@ int main(int argc, char** argv)
dev::eth::State state =c->state(index + 1,c->blockChain().numberHash(block)); dev::eth::State state =c->state(index + 1,c->blockChain().numberHash(block));
if (index < state.pending().size()) if (index < state.pending().size())
{ {
Executive e(state); Executive e(state, 0);
Transaction t = state.pending()[index]; Transaction t = state.pending()[index];
state = state.fromPending(index); state = state.fromPending(index);
bytes r = t.rlp(); bytes r = t.rlp();

1
libdevcore/vector_ref.h

@ -40,6 +40,7 @@ public:
vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); } vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); }
void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; } void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; }
void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); } void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); }
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
_T* begin() { return m_data; } _T* begin() { return m_data; }
_T* end() { return m_data + m_count; } _T* end() { return m_data + m_count; }

62
libethereum/Executive.cpp

@ -19,12 +19,13 @@
* @date 2014 * @date 2014
*/ */
#include "Executive.h"
#include <boost/timer.hpp> #include <boost/timer.hpp>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "Interface.h" #include "Interface.h"
#include "Executive.h"
#include "State.h" #include "State.h"
#include "ExtVM.h" #include "ExtVM.h"
using namespace std; using namespace std;
@ -88,32 +89,36 @@ bool Executive::setup(bytesConstRef _rlp)
if (m_t.isCreation()) if (m_t.isCreation())
return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender); return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender);
else else
return call(m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_sender); return call(m_t.receiveAddress(), m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_sender);
} }
bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress) bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)
{ {
m_isCreation = false;
// cnote << "Transferring" << formatBalance(_value) << "to receiver."; // cnote << "Transferring" << formatBalance(_value) << "to receiver.";
m_s.addBalance(_receiveAddress, _value); m_s.addBalance(_receiveAddress, _value);
auto it = !(_receiveAddress & ~h160(0xffffffff)) ? State::precompiled().find((unsigned)(u160)_receiveAddress) : State::precompiled().end(); auto it = !(_codeAddress & ~h160(0xffffffff)) ? State::precompiled().find((unsigned)(u160)_codeAddress) : State::precompiled().end();
if (it != State::precompiled().end()) if (it != State::precompiled().end())
{ {
bigint g = it->second.gas(_data); bigint g = it->second.gas(_data);
if (_gas < g) if (_gas < g)
{ {
m_endGas = 0; m_endGas = 0;
return false; m_excepted = true;
} }
else
{
m_endGas = (u256)(_gas - g); m_endGas = (u256)(_gas - g);
it->second.exec(_data, bytesRef()); m_precompiledOut = it->second.exec(_data);
return true; m_out = &m_precompiledOut;
} }
else if (m_s.addressHasCode(_receiveAddress)) }
else if (m_s.addressHasCode(_codeAddress))
{ {
m_vm = VMFactory::create(_gas); m_vm = VMFactory::create(_gas);
bytes const& c = m_s.code(_receiveAddress); bytes const& c = m_s.code(_codeAddress);
m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c)); m_ext = make_shared<ExtVM>(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_depth);
} }
else else
m_endGas = _gas; m_endGas = _gas;
@ -122,6 +127,8 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin) bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin)
{ {
m_isCreation = true;
// We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_newAddress, since // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_newAddress, since
// we delete it explicitly if we decide we need to revert. // we delete it explicitly if we decide we need to revert.
m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1))); m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1)));
@ -131,7 +138,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
// Execute _init. // Execute _init.
m_vm = VMFactory::create(_gas); m_vm = VMFactory::create(_gas);
m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init)); m_ext = make_shared<ExtVM>(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_depth);
return _init.empty(); return _init.empty();
} }
@ -160,17 +167,20 @@ bool Executive::go(OnOpFunc const& _onOp)
if (m_vm) if (m_vm)
{ {
boost::timer t; boost::timer t;
auto sgas = m_vm->gas(); // auto sgas = m_vm->gas();
try try
{ {
m_out = m_vm->go(*m_ext, _onOp); m_out = m_vm->go(*m_ext, _onOp);
m_endGas = m_vm->gas(); m_endGas = m_vm->gas();
m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds);
m_logs = m_ext->sub.logs; if (m_isCreation)
{
if (m_out.size() * c_createDataGas <= m_endGas) if (m_out.size() * c_createDataGas <= m_endGas)
m_endGas -= m_out.size() * c_createDataGas; m_endGas -= m_out.size() * c_createDataGas;
else else
m_out.reset(); m_out.reset();
m_s.m_cache[m_newAddress].setCode(m_out);
}
} }
catch (StepsDone const&) catch (StepsDone const&)
{ {
@ -180,16 +190,10 @@ bool Executive::go(OnOpFunc const& _onOp)
{ {
clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e); clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e);
m_endGas = 0;//m_vm->gas(); m_endGas = 0;//m_vm->gas();
m_excepted = true;
// Write state out only in the case of a non-excepted transaction. // Write state out only in the case of a non-excepted transaction.
m_ext->revert(); m_ext->revert();
// Explicitly delete a newly created address - this will still be in the reverted state.
/* if (m_newAddress)
{
m_s.m_cache.erase(m_newAddress);
m_newAddress = Address();
}*/
} }
catch (Exception const& _e) catch (Exception const& _e)
{ {
@ -201,23 +205,20 @@ bool Executive::go(OnOpFunc const& _onOp)
// TODO: AUDIT: check that this can never reasonably happen. Consider what to do if it does. // TODO: AUDIT: check that this can never reasonably happen. Consider what to do if it does.
cwarn << "Unexpected std::exception in VM. This is probably unrecoverable. " << _e.what(); cwarn << "Unexpected std::exception in VM. This is probably unrecoverable. " << _e.what();
} }
cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas); // cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas);
} }
return true; return true;
} }
u256 Executive::gas() const /*u256 Executive::gas() const
{ {
return m_vm ? m_vm->gas() : m_endGas; return m_vm ? m_vm->gas() : m_endGas;
} }*/
void Executive::finalize(OnOpFunc const&) void Executive::finalize(OnOpFunc const&)
{ {
if (m_t.isCreation() && !m_ext->sub.suicides.count(m_newAddress)) // SSTORE refunds.
{ m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds);
// creation - put code in place.
m_s.m_cache[m_newAddress].setCode(m_out);
}
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")";
m_s.addBalance(m_sender, m_endGas * m_t.gasPrice()); m_s.addBalance(m_sender, m_endGas * m_t.gasPrice());
@ -230,4 +231,7 @@ void Executive::finalize(OnOpFunc const&)
if (m_ext) if (m_ext)
for (auto a: m_ext->sub.suicides) for (auto a: m_ext->sub.suicides)
m_s.m_cache[a].kill(); m_s.m_cache[a].kill();
// Logs
m_logs = m_ext->sub.logs;
} }

20
libethereum/Executive.h

@ -27,7 +27,6 @@
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include <libevm/VMFace.h> #include <libevm/VMFace.h>
#include "Transaction.h" #include "Transaction.h"
#include "ExtVM.h"
namespace dev namespace dev
{ {
@ -35,21 +34,23 @@ namespace eth
{ {
class State; class State;
class ExtVM;
struct Manifest; struct Manifest;
struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; }; struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; };
class Executive class Executive
{ {
public: public:
Executive(State& _s): m_s(_s) {} Executive(State& _s, unsigned _level): m_s(_s), m_depth(_level) {}
~Executive() = default; ~Executive() = default;
Executive(Executive const&) = delete; Executive(Executive const&) = delete;
void operator=(Executive) = delete; void operator=(Executive) = delete;
bool setup(bytesConstRef _transaction); bool setup(bytesConstRef _transaction);
bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress);
bool call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress); bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress);
bool go(OnOpFunc const& _onOp = OnOpFunc()); bool go(OnOpFunc const& _onOp = OnOpFunc());
void finalize(OnOpFunc const& _onOp = OnOpFunc()); void finalize(OnOpFunc const& _onOp = OnOpFunc());
u256 gasUsed() const; u256 gasUsed() const;
@ -58,24 +59,29 @@ public:
Transaction const& t() const { return m_t; } Transaction const& t() const { return m_t; }
u256 gas() const; u256 endGas() const { return m_endGas; }
bytesConstRef out() const { return m_out; } bytesConstRef out() const { return m_out; }
h160 newAddress() const { return m_newAddress; } h160 newAddress() const { return m_newAddress; }
LogEntries const& logs() const { return m_logs; } LogEntries const& logs() const { return m_logs; }
bool excepted() const { return m_excepted; }
VMFace 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; } ExtVM const& ext() const { return *m_ext; }
State const& state() const { return m_s; }
private: private:
State& m_s; State& m_s;
std::unique_ptr<ExtVM> m_ext; std::shared_ptr<ExtVM> m_ext;
std::unique_ptr<VMFace> m_vm; std::unique_ptr<VMFace> m_vm;
bytesConstRef m_out; bytes m_precompiledOut; ///< Used for the output when there is no VM for a contract (i.e. precompiled).
bytesConstRef m_out; ///< Holds the copyable output.
Address m_newAddress; Address m_newAddress;
Transaction m_t; Transaction m_t;
bool m_isCreation;
bool m_excepted = false;
unsigned m_depth = 0;
Address m_sender; Address m_sender;
u256 m_endGas; u256 m_endGas;

10
libethereum/ExtVM.h

@ -55,17 +55,17 @@ public:
virtual bytes const& codeAt(Address _a) override final { return m_s.code(_a); } virtual bytes const& codeAt(Address _a) override final { return m_s.code(_a); }
/// Create a new contract. /// Create a new contract.
virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, OnOpFunc const& _onOp = OnOpFunc()) override final virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final
{ {
// Increment associated nonce for sender. // Increment associated nonce for sender.
m_s.noteSending(myAddress); m_s.noteSending(myAddress);
return m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin, &sub, _onOp, depth + 1); return m_s.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, sub, _onOp, depth + 1);
} }
/// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller.
virtual bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out, OnOpFunc const& _onOp = {}, Address _myAddressOverride = {}, Address _codeAddressOverride = {}) override final virtual bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp = {}, Address _myAddressOverride = {}, Address _codeAddressOverride = {}) override final
{ {
return m_s.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &sub, _onOp, depth + 1); return m_s.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, _out, origin, sub, _onOp, depth + 1);
} }
/// Read address's balance. /// Read address's balance.
@ -86,7 +86,7 @@ public:
/// Revert any changes made (by any of the other calls). /// Revert any changes made (by any of the other calls).
/// @TODO check call site for the parent manifest being discarded. /// @TODO check call site for the parent manifest being discarded.
virtual void revert() override final { m_s.m_cache = m_origCache; } virtual void revert() override final { m_s.m_cache = m_origCache; sub.clear(); }
State& state() const { return m_s; } State& state() const { return m_s; }

153
libethereum/State.cpp

@ -42,7 +42,7 @@ using namespace dev::eth;
static const u256 c_blockReward = 1500 * finney; static const u256 c_blockReward = 1500 * finney;
void ecrecoverCode(bytesConstRef _in, bytesRef _out) bytes ecrecoverCode(bytesConstRef _in)
{ {
struct inType struct inType
{ {
@ -54,38 +54,38 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
memcpy(&in, _in.data(), min(_in.size(), sizeof(in))); memcpy(&in, _in.data(), min(_in.size(), sizeof(in)));
memset(_out.data(), 0, _out.size()); h256 ret;
if ((u256)in.v > 28) if ((u256)in.v > 28)
return; return ret.asBytes();
SignatureStruct sig{in.r, in.s, (byte)((int)(u256)in.v - 27)}; SignatureStruct sig{in.r, in.s, (byte)((int)(u256)in.v - 27)};
if (!sig.isValid()) if (!sig.isValid())
return; return ret.asBytes();
h256 ret;
byte pubkey[65]; byte pubkey[65];
int pubkeylen = 65; int pubkeylen = 65;
secp256k1_start(); secp256k1_start();
if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27)) if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27))
ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64)); ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64));
memset(ret.data(), 0, 12); return ret.asBytes();
memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret)));
} }
void sha256Code(bytesConstRef _in, bytesRef _out) bytes sha256Code(bytesConstRef _in)
{ {
h256 ret; bytes ret(32);
sha256(_in, bytesRef(ret.data(), 32)); sha256(_in, &ret);
memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); return ret;
} }
void ripemd160Code(bytesConstRef _in, bytesRef _out) bytes ripemd160Code(bytesConstRef _in)
{ {
h256 ret; bytes ret(32);
ripemd160(_in, bytesRef(ret.data(), 32)); ripemd160(_in, &ret);
memset(_out.data(), 0, std::min<int>(12, _out.size())); // leaves the 20-byte hash left-aligned. we want it right-aligned:
if (_out.size() > 12) memmove(ret.data() + 12, ret.data(), 20);
memcpy(_out.data() + 12, &ret, min(_out.size() - 12, sizeof(ret))); memset(ret.data(), 0, 12);
return ret;
} }
const std::map<unsigned, PrecompiledAddress> State::c_precompiled = const std::map<unsigned, PrecompiledAddress> State::c_precompiled =
@ -1119,7 +1119,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
auto h = rootHash(); auto h = rootHash();
#endif #endif
Executive e(*this); Executive e(*this, 0);
e.setup(_rlp); e.setup(_rlp);
u256 startGasUsed = gasUsed(); u256 startGasUsed = gasUsed();
@ -1174,117 +1174,30 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
return e.gasUsed(); return e.gasUsed();
} }
bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress, SubState* o_sub, OnOpFunc const& _onOp, unsigned _level) bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256& io_gas, bytesRef _out, Address _originAddress, SubState& io_sub, OnOpFunc const& _onOp, unsigned _level)
{ {
if (!_originAddress) Executive e(*this, _level);
_originAddress = _senderAddress; if (!e.call(_receiveAddress, _codeAddress, _senderAddress, _value, _gasPrice, _data, io_gas, _originAddress))
// cnote << "Transferring" << formatBalance(_value) << "to receiver.";
addBalance(_receiveAddress, _value);
auto it = !(_codeAddress & ~h160(0xffffffff)) ? c_precompiled.find((unsigned)(u160)_codeAddress) : c_precompiled.end();
if (it != c_precompiled.end())
{ {
bigint g = it->second.gas(_data); e.go(_onOp);
if (*_gas < g) io_sub += e.ext().sub;
{
*_gas = 0;
return false;
} }
io_gas = e.endGas();
e.out().copyTo(_out);
*_gas -= (u256)g; return !e.excepted();
it->second.exec(_data, _out);
}
else if (addressHasCode(_codeAddress))
{
auto vm = VMFactory::create(*_gas);
ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), _level);
try
{
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();
// Write state out only in the case of a non-excepted transaction.
return true;
}
catch (VMException const& _e)
{
clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e);
evm.revert();
*_gas = 0;
return false;
} }
catch (Exception const& _e)
{
cwarn << "Unexpected exception in VM: " << diagnostic_information(_e) << ". This is exceptionally bad.";
// TODO: use fallback known-safe VM.
// AUDIT: THIS SHOULD NEVER HAPPEN! PROVE IT!
throw;
}
catch (std::exception const& _e)
{
cwarn << "Unexpected exception in VM: " << _e.what() << ". This is exceptionally bad.";
// TODO: use fallback known-safe VM.
// AUDIT: THIS SHOULD NEVER HAPPEN! PROVE IT!
throw;
}
}
return true;
}
h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, OnOpFunc const& _onOp, unsigned _level)
{
if (!_origin)
_origin = _sender;
Address newAddress = right160(sha3(rlpList(_sender, transactionsFrom(_sender) - 1)));
// Set up new account...
m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception);
// Execute init code.
auto vm = VMFactory::create(*_gas);
ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, _level);
bytesConstRef out;
try h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256& io_gas, bytesConstRef _code, Address _origin, SubState& io_sub, OnOpFunc const& _onOp, unsigned _level)
{
out = vm->go(evm, _onOp);
if (o_sub)
*o_sub += evm.sub;
*_gas = vm->gas();
if (out.size() * c_createDataGas <= *_gas)
*_gas -= out.size() * c_createDataGas;
else
out.reset();
// Set code.
if (!evm.sub.suicides.count(newAddress))
m_cache[newAddress].setCode(out);
}
catch (VMException const& _e)
{ {
clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e); Executive e(*this, _level);
evm.revert(); if (!e.create(_sender, _endowment, _gasPrice, io_gas, _code, _origin))
*_gas = 0;
}
catch (Exception const& _e)
{
// TODO: AUDIT: check that this can never reasonably happen. Consider what to do if it does.
cwarn << "Unexpected exception in VM. There may be a bug in this implementation. " << diagnostic_information(_e);
throw;
}
catch (std::exception const& _e)
{ {
// TODO: AUDIT: check that this can never reasonably happen. Consider what to do if it does. e.go(_onOp);
cwarn << "Unexpected std::exception in VM. This is probably unrecoverable. " << _e.what(); io_sub += e.ext().sub;
throw;
} }
io_gas = e.endGas();
return newAddress; return e.newAddress();
} }
State State::fromPending(unsigned _i) const State State::fromPending(unsigned _i) const

6
libethereum/State.h

@ -55,7 +55,7 @@ struct StateDetail: public LogChannel { static const char* name() { return "/S/"
struct PrecompiledAddress struct PrecompiledAddress
{ {
std::function<bigint(bytesConstRef)> gas; std::function<bigint(bytesConstRef)> gas;
std::function<void(bytesConstRef, bytesRef)> exec; std::function<bytes(bytesConstRef)> exec;
}; };
/** /**
@ -276,12 +276,12 @@ private:
// We assume all instrinsic fees are paid up before this point. // We assume all instrinsic fees are paid up before this point.
/// Execute a contract-creation transaction. /// Execute a contract-creation transaction.
h160 create(Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address(), SubState* o_sub = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0); h160 create(Address _txSender, u256 _endowment, u256 _gasPrice, u256& io_gas, bytesConstRef _code, Address _originAddress, SubState& io_sub, OnOpFunc const& _onOp, unsigned _level);
/// Execute a call. /// Execute a call.
/// @a _gas points to the amount of gas to use for the call, and will lower it accordingly. /// @a _gas points to the amount of gas to use for the call, and will lower it accordingly.
/// @returns false if the call ran out of gas before completion. true otherwise. /// @returns false if the call ran out of gas before completion. true otherwise.
bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256* _gas, bytesRef _out, Address _originAddress = Address(), SubState* o_sub = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0); bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256& io_gas, bytesRef _out, Address _originAddress, SubState& io_sub, OnOpFunc const& _onOp, unsigned _level);
/// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock). /// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock).
void resetCurrent(); void resetCurrent();

11
libevm/ExtVMFace.h

@ -83,6 +83,13 @@ struct SubState
logs += _s.logs; logs += _s.logs;
return *this; return *this;
} }
void clear()
{
suicides.clear();
logs.clear();
refunds = 0;
}
}; };
class ExtVMFace; class ExtVMFace;
@ -129,10 +136,10 @@ public:
virtual void suicide(Address) { sub.suicides.insert(myAddress); } virtual void suicide(Address) { sub.suicides.insert(myAddress); }
/// Create a new (contract) account. /// Create a new (contract) account.
virtual h160 create(u256, u256*, bytesConstRef, OnOpFunc const&) { return h160(); } virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); }
/// Make a new message call. /// Make a new message call.
virtual bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } virtual bool call(Address, u256, bytesConstRef, u256&, bytesRef, OnOpFunc const&, Address, Address) { return false; }
/// Revert any changes made (by any of the other calls). /// Revert any changes made (by any of the other calls).
virtual void log(h256s&& _topics, bytesConstRef _data) { sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes())); } virtual void log(h256s&& _topics, bytesConstRef _data) { sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes())); }

4
libevm/VM.h

@ -798,7 +798,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
if (_ext.depth == 1024) if (_ext.depth == 1024)
BOOST_THROW_EXCEPTION(OutOfGas()); BOOST_THROW_EXCEPTION(OutOfGas());
_ext.subBalance(endowment); _ext.subBalance(endowment);
m_stack.push_back((u160)_ext.create(endowment, &m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp));
} }
else else
m_stack.push_back(0); m_stack.push_back(0);
@ -828,7 +828,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st
if (_ext.depth == 1024) if (_ext.depth == 1024)
BOOST_THROW_EXCEPTION(OutOfGas()); BOOST_THROW_EXCEPTION(OutOfGas());
_ext.subBalance(value); _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, Address(), receiveAddress)); 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 else
m_stack.push_back(0); m_stack.push_back(0);

4
test/solidityExecutionFramework.h

@ -117,7 +117,7 @@ private:
void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0) void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0)
{ {
m_state.addBalance(m_sender, _value); // just in case m_state.addBalance(m_sender, _value); // just in case
eth::Executive executive(m_state); eth::Executive executive(m_state, 0);
eth::Transaction t = _isCreation ? eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) eth::Transaction t = _isCreation ? eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec())
: eth::Transaction(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); : eth::Transaction(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec());
bytes transactionRLP = t.rlp(); bytes transactionRLP = t.rlp();
@ -137,7 +137,7 @@ private:
else else
{ {
BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
BOOST_REQUIRE(!executive.call(m_contractAddress, m_sender, _value, m_gasPrice, &_data, m_gas, m_sender)); BOOST_REQUIRE(!executive.call(m_contractAddress, m_contractAddress, m_sender, _value, m_gasPrice, &_data, m_gas, m_sender));
} }
BOOST_REQUIRE(executive.go()); BOOST_REQUIRE(executive.go());
m_state.noteSending(m_sender); m_state.noteSending(m_sender);

2
test/state.cpp

@ -45,7 +45,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
{ {
for (auto& i: v.get_obj()) for (auto& i: v.get_obj())
{ {
cnote << i.first; cerr << i.first << endl;
mObject& o = i.second.get_obj(); mObject& o = i.second.get_obj();
BOOST_REQUIRE(o.count("env") > 0); BOOST_REQUIRE(o.count("env") > 0);

3
test/trie.cpp

@ -54,7 +54,6 @@ BOOST_AUTO_TEST_CASE(trie_tests)
{ {
string testPath = test::getTestPath(); string testPath = test::getTestPath();
testPath += "/TrieTests"; testPath += "/TrieTests";
cnote << "Testing Trie..."; cnote << "Testing Trie...";
@ -245,6 +244,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
BOOST_AUTO_TEST_CASE(trieLowerBound) BOOST_AUTO_TEST_CASE(trieLowerBound)
{ {
cnote << "Stress-testing Trie.lower_bound..."; cnote << "Stress-testing Trie.lower_bound...";
if (0)
{ {
MemoryDB dm; MemoryDB dm;
EnforceRefs e(dm, true); EnforceRefs e(dm, true);
@ -290,6 +290,7 @@ BOOST_AUTO_TEST_CASE(trieLowerBound)
BOOST_AUTO_TEST_CASE(trieStess) BOOST_AUTO_TEST_CASE(trieStess)
{ {
cnote << "Stress-testing Trie..."; cnote << "Stress-testing Trie...";
if (0)
{ {
MemoryDB m; MemoryDB m;
MemoryDB dm; MemoryDB dm;

8
test/vm.cpp

@ -34,18 +34,18 @@ using namespace dev::test;
FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix. FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix.
ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, _depth) {} ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, _depth) {}
h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&)
{ {
Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress]))));
Transaction t(_endowment, gasPrice, *_gas, _init.toBytes()); Transaction t(_endowment, gasPrice, io_gas, _init.toBytes());
callcreates.push_back(t); callcreates.push_back(t);
return na; return na;
} }
bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride)
{ {
Transaction t(_value, gasPrice, *_gas, _receiveAddress, _data.toVector()); Transaction t(_value, gasPrice, io_gas, _receiveAddress, _data.toVector());
callcreates.push_back(t); callcreates.push_back(t);
(void)_out; (void)_out;
(void)_myAddressOverride; (void)_myAddressOverride;

4
test/vm.h

@ -55,8 +55,8 @@ public:
virtual u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); } virtual u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); }
virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); }
virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); }
virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override; virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&) override;
virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override;
void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data);
void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);

5
test/whisperTopic.cpp

@ -33,7 +33,8 @@ BOOST_AUTO_TEST_SUITE(whisper)
BOOST_AUTO_TEST_CASE(topic) BOOST_AUTO_TEST_CASE(topic)
{ {
cnote << "Testing Whisper..."; cnote << "Testing Whisper...";
// g_logVerbosity = 0; auto oldLogVerbosity = g_logVerbosity;
g_logVerbosity = 0;
bool started = false; bool started = false;
unsigned result = 0; unsigned result = 0;
@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(topic)
} }
listener.join(); listener.join();
// g_logVerbosity = 0; g_logVerbosity = oldLogVerbosity;
BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81); BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81);
} }

Loading…
Cancel
Save