From 9e2eb149af7038c3efb1bba1f80cfeb8571b1646 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 13:33:42 +0100 Subject: [PATCH 1/6] Beginnings of cleaning up the Executive/State code. --- alethzero/MainWin.cpp | 4 +-- eth/main.cpp | 2 +- libdevcore/vector_ref.h | 1 + libethereum/Executive.cpp | 41 +++++++++++++------------ libethereum/Executive.h | 13 +++++--- libethereum/ExtVM.h | 10 +++--- libethereum/State.cpp | 51 ++++++++++++++++++++----------- libethereum/State.h | 4 +-- libevm/ExtVMFace.h | 11 +++++-- libevm/VM.h | 4 +-- test/jsonrpc.cpp | 2 +- test/solidityExecutionFramework.h | 4 +-- test/trie.cpp | 3 +- test/vm.cpp | 8 ++--- test/vm.h | 4 +-- test/whisperTopic.cpp | 5 +-- 16 files changed, 99 insertions(+), 68 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a240f64e1..0e36c7737 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1350,7 +1350,7 @@ void Main::on_debugCurrent_triggered() { unsigned txi = item->data(Qt::UserRole + 1).toInt(); m_executiveState = ethereum()->state(txi + 1, h); - m_currentExecution = unique_ptr(new Executive(m_executiveState)); + m_currentExecution = unique_ptr(new Executive(m_executiveState, 0)); Transaction t = m_executiveState.pending()[txi]; m_executiveState = m_executiveState.fromPending(txi); auto r = t.rlp(); @@ -1855,7 +1855,7 @@ void Main::on_debug_clicked() { Secret s = i.secret(); m_executiveState = ethereum()->postState(); - m_currentExecution = unique_ptr(new Executive(m_executiveState)); + m_currentExecution = unique_ptr(new Executive(m_executiveState, 0)); Transaction t = isCreation() ? 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); diff --git a/eth/main.cpp b/eth/main.cpp index 0113fa1a5..49c5fdf56 100644 --- a/eth/main.cpp +++ b/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)); if (index < state.pending().size()) { - Executive e(state); + Executive e(state, 0); Transaction t = state.pending()[index]; state = state.fromPending(index); bytes r = t.rlp(); diff --git a/libdevcore/vector_ref.h b/libdevcore/vector_ref.h index be2fea13c..db46d62f6 100644 --- a/libdevcore/vector_ref.h +++ b/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>(); } 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 copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); } _T* begin() { return m_data; } _T* end() { return m_data + m_count; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 007896d75..c81dd7ed8 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -19,12 +19,13 @@ * @date 2014 */ +#include "Executive.h" + #include #include #include #include #include "Interface.h" -#include "Executive.h" #include "State.h" #include "ExtVM.h" using namespace std; @@ -88,11 +89,12 @@ bool Executive::setup(bytesConstRef _rlp) if (m_t.isCreation()) return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender); 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."; m_s.addBalance(_receiveAddress, _value); @@ -109,11 +111,11 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu it->second.exec(_data, bytesRef()); return true; } - else if (m_s.addressHasCode(_receiveAddress)) + else if (m_s.addressHasCode(_codeAddress)) { 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_ext = make_shared(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_depth); } else m_endGas = _gas; @@ -122,6 +124,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) { + 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 delete it explicitly if we decide we need to revert. m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1))); @@ -131,7 +135,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // Execute _init. m_vm = VMFactory::create(_gas); - m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init)); + m_ext = make_shared(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_depth); return _init.empty(); } @@ -163,14 +167,18 @@ bool Executive::go(OnOpFunc const& _onOp) auto sgas = m_vm->gas(); try { - m_out = m_vm->go(*m_ext, _onOp); + m_out = m_vm->go(*m_ext, _onOp, 0); 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_out.size() * c_createDataGas <= m_endGas) - m_endGas -= m_out.size() * c_createDataGas; - else - m_out.reset(); + + if (m_isCreation) + { + if (m_out.size() * c_createDataGas <= m_endGas) + m_endGas -= m_out.size() * c_createDataGas; + else + m_out.reset(); + } } catch (StepsDone const&) { @@ -184,12 +192,7 @@ bool Executive::go(OnOpFunc const& _onOp) // Write state out only in the case of a non-excepted transaction. 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(); - }*/ + m_excepted = true; } catch (Exception const& _e) { @@ -214,12 +217,10 @@ u256 Executive::gas() const void Executive::finalize(OnOpFunc const&) { if (m_t.isCreation() && !m_ext->sub.suicides.count(m_newAddress)) - { // 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()); u256 feesEarned = (m_t.gas() - m_endGas) * m_t.gasPrice(); diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 9e47bbfbf..fa438f025 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -27,7 +27,6 @@ #include #include #include "Transaction.h" -#include "ExtVM.h" namespace dev { @@ -35,21 +34,23 @@ namespace eth { class State; +class ExtVM; 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(State& _s, unsigned _level): m_s(_s), m_depth(_level) {} ~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); - 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()); void finalize(OnOpFunc const& _onOp = OnOpFunc()); u256 gasUsed() const; @@ -63,6 +64,7 @@ public: bytesConstRef out() const { return m_out; } h160 newAddress() const { return m_newAddress; } LogEntries const& logs() const { return m_logs; } + bool excepted() const { return m_excepted; } VMFace const& vm() const { return *m_vm; } State const& state() const { return m_s; } @@ -70,12 +72,15 @@ public: private: State& m_s; - std::unique_ptr m_ext; + std::shared_ptr m_ext; std::unique_ptr m_vm; bytesConstRef m_out; Address m_newAddress; Transaction m_t; + bool m_isCreation; + bool m_excepted = false; + unsigned m_depth = 0; Address m_sender; u256 m_endGas; diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index ad1045d3f..d4937bcd5 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -55,17 +55,17 @@ public: virtual bytes const& codeAt(Address _a) override final { return m_s.code(_a); } /// 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 = OnOpFunc()) override final { // Increment associated nonce for sender. 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. - 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. @@ -86,7 +86,7 @@ public: /// Revert any changes made (by any of the other calls). /// @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; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 1d6ad3480..f2b5d7283 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1119,7 +1119,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) auto h = rootHash(); #endif - Executive e(*this); + Executive e(*this, 0); e.setup(_rlp); u256 startGasUsed = gasUsed(); @@ -1174,8 +1174,24 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) 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 0 + // TODO: TEST TEST TEST!!! + Executive e(*this, _level); + + if (!e.call(_receiveAddress, _codeAddress, _senderAddress, _value, _gasPrice, _data, io_gas, _originAddress)) + { + e.go(_onOp); + io_sub += e.ext().sub; + } + + e.out().copyTo(_out); + io_gas = e.gas(); + + return !e.excepted(); + +#else if (!_originAddress) _originAddress = _senderAddress; @@ -1186,26 +1202,25 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA if (it != c_precompiled.end()) { bigint g = it->second.gas(_data); - if (*_gas < g) + if (io_gas < g) { - *_gas = 0; + io_gas = 0; return false; } - *_gas -= (u256)g; + io_gas -= (u256)g; it->second.exec(_data, _out); } else if (addressHasCode(_codeAddress)) { - auto vm = VMFactory::create(*_gas); + auto vm = VMFactory::create(io_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(); + io_sub += evm.sub; + io_gas = vm->gas(); // Write state out only in the case of a non-excepted transaction. return true; } @@ -1213,7 +1228,7 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA { clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e); evm.revert(); - *_gas = 0; + io_gas = 0; return false; } catch (Exception const& _e) @@ -1232,9 +1247,10 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } } return true; +#endif } -h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, OnOpFunc const& _onOp, unsigned _level) +h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256& io_gas, bytesConstRef _code, Address _origin, SubState& io_sub, OnOpFunc const& _onOp, unsigned _level) { if (!_origin) _origin = _sender; @@ -1245,19 +1261,18 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. - auto vm = VMFactory::create(*_gas); + auto vm = VMFactory::create(io_gas); ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, _level); bytesConstRef out; try { out = vm->go(evm, _onOp); - if (o_sub) - *o_sub += evm.sub; - *_gas = vm->gas(); + io_sub += evm.sub; + io_gas = vm->gas(); - if (out.size() * c_createDataGas <= *_gas) - *_gas -= out.size() * c_createDataGas; + if (out.size() * c_createDataGas <= io_gas) + io_gas -= out.size() * c_createDataGas; else out.reset(); @@ -1269,7 +1284,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, { clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e); evm.revert(); - *_gas = 0; + io_gas = 0; } catch (Exception const& _e) { diff --git a/libethereum/State.h b/libethereum/State.h index 10d73f671..dd83a83ee 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -276,12 +276,12 @@ private: // We assume all instrinsic fees are paid up before this point. /// 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. /// @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. - 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). void resetCurrent(); diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 24c7dfcda..b8c4184ab 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -83,6 +83,13 @@ struct SubState logs += _s.logs; return *this; } + + void clear() + { + suicides.clear(); + logs.clear(); + refunds = 0; + } }; class ExtVMFace; @@ -129,10 +136,10 @@ public: virtual void suicide(Address) { sub.suicides.insert(myAddress); } /// 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. - 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). virtual void log(h256s&& _topics, bytesConstRef _data) { sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes())); } diff --git a/libevm/VM.h b/libevm/VM.h index 6f3229920..09a1f6d26 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -798,7 +798,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st if (_ext.depth == 1024) BOOST_THROW_EXCEPTION(OutOfGas()); _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 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) BOOST_THROW_EXCEPTION(OutOfGas()); _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, Address(), receiveAddress)); } else m_stack.push_back(0); diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 20ffc6d54..970957b52 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -43,7 +43,7 @@ using namespace dev; using namespace dev::eth; namespace js = json_spirit; -WebThreeDirect *web3; +WebThreeDirect* web3; unique_ptr jsonrpcServer; unique_ptr jsonrpcClient; diff --git a/test/solidityExecutionFramework.h b/test/solidityExecutionFramework.h index 9d40e8a46..91ee7ad6a 100644 --- a/test/solidityExecutionFramework.h +++ b/test/solidityExecutionFramework.h @@ -117,7 +117,7 @@ private: void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0) { 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(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); bytes transactionRLP = t.rlp(); @@ -137,7 +137,7 @@ private: else { 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()); m_state.noteSending(m_sender); diff --git a/test/trie.cpp b/test/trie.cpp index 3f072a6d1..0cf87c212 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -54,7 +54,6 @@ BOOST_AUTO_TEST_CASE(trie_tests) { string testPath = test::getTestPath(); - testPath += "/TrieTests"; cnote << "Testing Trie..."; @@ -245,6 +244,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) BOOST_AUTO_TEST_CASE(trieLowerBound) { cnote << "Stress-testing Trie.lower_bound..."; + if (0) { MemoryDB dm; EnforceRefs e(dm, true); @@ -290,6 +290,7 @@ BOOST_AUTO_TEST_CASE(trieLowerBound) BOOST_AUTO_TEST_CASE(trieStess) { cnote << "Stress-testing Trie..."; + if (0) { MemoryDB m; MemoryDB dm; diff --git a/test/vm.cpp b/test/vm.cpp index d8e85383c..f05981d9e 100644 --- a/test/vm.cpp +++ b/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. 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])))); - Transaction t(_endowment, gasPrice, *_gas, _init.toBytes()); + Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); callcreates.push_back(t); 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); (void)_out; (void)_myAddressOverride; diff --git a/test/vm.h b/test/vm.h index 3d4b88d54..ff948cbf8 100644 --- a/test/vm.h +++ b/test/vm.h @@ -55,8 +55,8 @@ public: 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 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 bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) 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& io_gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index c5e59332d..79adf3d6a 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -33,7 +33,8 @@ BOOST_AUTO_TEST_SUITE(whisper) BOOST_AUTO_TEST_CASE(topic) { cnote << "Testing Whisper..."; -// g_logVerbosity = 0; + auto oldLogVerbosity = g_logVerbosity; + g_logVerbosity = 0; bool started = false; unsigned result = 0; @@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(topic) } listener.join(); -// g_logVerbosity = 0; + g_logVerbosity = oldLogVerbosity; BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81); } From ac5a0ff1fb6dce456b2a3484c322cc498dfdb51c Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 16:04:34 +0100 Subject: [PATCH 2/6] Minor fix for execution. --- libethereum/Executive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index c81dd7ed8..9d4e9c1e6 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -167,7 +167,7 @@ bool Executive::go(OnOpFunc const& _onOp) auto sgas = m_vm->gas(); try { - m_out = m_vm->go(*m_ext, _onOp, 0); + m_out = m_vm->go(*m_ext, _onOp); m_endGas = m_vm->gas(); m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); m_logs = m_ext->sub.logs; From 5cc2152dd02909084a632544e2aa70bb23d31704 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 17:22:32 +0100 Subject: [PATCH 3/6] Cleanups. --- libethereum/Executive.cpp | 25 +++++++++++++++---------- libethereum/Executive.h | 2 +- libethereum/ExtVM.h | 2 +- libethereum/State.cpp | 3 +-- libevm/VM.h | 2 +- test/state.cpp | 2 +- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 9d4e9c1e6..e5a8e6b11 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -105,11 +105,13 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen if (_gas < g) { m_endGas = 0; - return false; + m_excepted = true; + } + else + { + m_endGas = (u256)(_gas - g); + it->second.exec(_data, bytesRef()); } - m_endGas = (u256)(_gas - g); - it->second.exec(_data, bytesRef()); - return true; } else if (m_s.addressHasCode(_codeAddress)) { @@ -169,8 +171,6 @@ bool Executive::go(OnOpFunc const& _onOp) { m_out = m_vm->go(*m_ext, _onOp); 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) { @@ -188,11 +188,10 @@ bool Executive::go(OnOpFunc const& _onOp) { clog(StateChat) << "Safe VM Exception: " << diagnostic_information(_e); m_endGas = 0;//m_vm->gas(); + m_excepted = true; // Write state out only in the case of a non-excepted transaction. m_ext->revert(); - - m_excepted = true; } catch (Exception const& _e) { @@ -209,10 +208,10 @@ bool Executive::go(OnOpFunc const& _onOp) return true; } -u256 Executive::gas() const +/*u256 Executive::gas() const { return m_vm ? m_vm->gas() : m_endGas; -} +}*/ void Executive::finalize(OnOpFunc const&) { @@ -220,6 +219,9 @@ void Executive::finalize(OnOpFunc const&) // creation - put code in place. m_s.m_cache[m_newAddress].setCode(m_out); + // SSTORE refunds. + m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); + // 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()); @@ -231,4 +233,7 @@ void Executive::finalize(OnOpFunc const&) if (m_ext) for (auto a: m_ext->sub.suicides) m_s.m_cache[a].kill(); + + // Logs + m_logs = m_ext->sub.logs; } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index fa438f025..068439d87 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -59,7 +59,7 @@ public: Transaction const& t() const { return m_t; } - u256 gas() const; + u256 endGas() const { return m_endGas; } bytesConstRef out() const { return m_out; } h160 newAddress() const { return m_newAddress; } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index d4937bcd5..8c04ff113 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -55,7 +55,7 @@ public: virtual bytes const& codeAt(Address _a) override final { return m_s.code(_a); } /// Create a new contract. - virtual h160 create(u256 _endowment, u256& io_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. m_s.noteSending(myAddress); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f2b5d7283..07dcccf2a 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -1187,10 +1187,9 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } e.out().copyTo(_out); - io_gas = e.gas(); + io_gas = e.endGas(); return !e.excepted(); - #else if (!_originAddress) _originAddress = _senderAddress; diff --git a/libevm/VM.h b/libevm/VM.h index 09a1f6d26..3eb330fcd 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -828,7 +828,7 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st if (_ext.depth == 1024) BOOST_THROW_EXCEPTION(OutOfGas()); _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 m_stack.push_back(0); diff --git a/test/state.cpp b/test/state.cpp index 07c8373e2..3fe0fe30b 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -45,7 +45,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) { for (auto& i: v.get_obj()) { - cnote << i.first; + cerr << i.first << endl; mObject& o = i.second.get_obj(); BOOST_REQUIRE(o.count("env") > 0); From daa6b8f84951978d08458306cafa12a1d0f2ec72 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 19:44:09 +0100 Subject: [PATCH 4/6] Refactor state to use executive for calls. --- libethereum/Executive.cpp | 11 ++++++----- libethereum/Executive.h | 3 ++- libethereum/State.cpp | 32 ++++++++++++-------------------- libethereum/State.h | 2 +- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index e5a8e6b11..d568996c3 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -98,7 +98,7 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen // cnote << "Transferring" << formatBalance(_value) << "to receiver."; 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()) { bigint g = it->second.gas(_data); @@ -110,13 +110,14 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen else { m_endGas = (u256)(_gas - g); - it->second.exec(_data, bytesRef()); + m_precompiledOut = it->second.exec(_data); + m_out = &m_precompiledOut; } } else if (m_s.addressHasCode(_codeAddress)) { m_vm = VMFactory::create(_gas); - bytes const& c = m_s.code(_receiveAddress); + bytes const& c = m_s.code(_codeAddress); m_ext = make_shared(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_depth); } else @@ -166,7 +167,7 @@ bool Executive::go(OnOpFunc const& _onOp) if (m_vm) { boost::timer t; - auto sgas = m_vm->gas(); +// auto sgas = m_vm->gas(); try { m_out = m_vm->go(*m_ext, _onOp); @@ -203,7 +204,7 @@ bool Executive::go(OnOpFunc const& _onOp) // 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(); } - cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas); +// cnote << "VM took:" << t.elapsed() << "; gas used: " << (sgas - m_endGas); } return true; } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 068439d87..d6de1491e 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -74,7 +74,8 @@ private: State& m_s; std::shared_ptr m_ext; std::unique_ptr 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; Transaction m_t; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 07dcccf2a..65f3cdeca 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -42,7 +42,7 @@ using namespace dev::eth; static const u256 c_blockReward = 1500 * finney; -void ecrecoverCode(bytesConstRef _in, bytesRef _out) +bytes ecrecoverCode(bytesConstRef _in) { struct inType { @@ -54,38 +54,35 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out) memcpy(&in, _in.data(), min(_in.size(), sizeof(in))); - memset(_out.data(), 0, _out.size()); + h256 ret; + if ((u256)in.v > 28) - return; + return ret.asBytes(); SignatureStruct sig{in.r, in.s, (byte)((int)(u256)in.v - 27)}; if (!sig.isValid()) - return; + return ret.asBytes(); - h256 ret; byte pubkey[65]; int pubkeylen = 65; secp256k1_start(); 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)); - memset(ret.data(), 0, 12); - memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); + return ret.asBytes(); } -void sha256Code(bytesConstRef _in, bytesRef _out) +bytes sha256Code(bytesConstRef _in) { h256 ret; sha256(_in, bytesRef(ret.data(), 32)); - memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); + return ret.asBytes(); } -void ripemd160Code(bytesConstRef _in, bytesRef _out) +bytes ripemd160Code(bytesConstRef _in) { h256 ret; ripemd160(_in, bytesRef(ret.data(), 32)); - memset(_out.data(), 0, std::min(12, _out.size())); - if (_out.size() > 12) - memcpy(_out.data() + 12, &ret, min(_out.size() - 12, sizeof(ret))); + return ret.asBytes(); } const std::map State::c_precompiled = @@ -1176,24 +1173,19 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) 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 0 +#if 1 // TODO: TEST TEST TEST!!! Executive e(*this, _level); - if (!e.call(_receiveAddress, _codeAddress, _senderAddress, _value, _gasPrice, _data, io_gas, _originAddress)) { e.go(_onOp); io_sub += e.ext().sub; } - - e.out().copyTo(_out); io_gas = e.endGas(); + e.out().copyTo(_out); return !e.excepted(); #else - if (!_originAddress) - _originAddress = _senderAddress; - // cnote << "Transferring" << formatBalance(_value) << "to receiver."; addBalance(_receiveAddress, _value); diff --git a/libethereum/State.h b/libethereum/State.h index dd83a83ee..744f82e10 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -55,7 +55,7 @@ struct StateDetail: public LogChannel { static const char* name() { return "/S/" struct PrecompiledAddress { std::function gas; - std::function exec; + std::function exec; }; /** From 5412dbb9e8ba7ad13f21bebe0cb088322b07a6e2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 20:38:49 +0100 Subject: [PATCH 5/6] Remove old code, refactor State::call, State::create to use Executive. --- libethereum/Executive.cpp | 5 +- libethereum/Executive.h | 2 +- libethereum/State.cpp | 120 ++++---------------------------------- 3 files changed, 14 insertions(+), 113 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index d568996c3..deb3da33e 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -179,6 +179,7 @@ bool Executive::go(OnOpFunc const& _onOp) m_endGas -= m_out.size() * c_createDataGas; else m_out.reset(); + m_s.m_cache[m_newAddress].setCode(m_out); } } catch (StepsDone const&) @@ -216,10 +217,6 @@ bool Executive::go(OnOpFunc const& _onOp) void Executive::finalize(OnOpFunc const&) { - if (m_t.isCreation() && !m_ext->sub.suicides.count(m_newAddress)) - // creation - put code in place. - m_s.m_cache[m_newAddress].setCode(m_out); - // SSTORE refunds. m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); diff --git a/libethereum/Executive.h b/libethereum/Executive.h index d6de1491e..c5baada1d 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -67,8 +67,8 @@ public: bool excepted() const { return m_excepted; } VMFace const& vm() const { return *m_vm; } - State const& state() const { return m_s; } ExtVM const& ext() const { return *m_ext; } + State const& state() const { return m_s; } private: State& m_s; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 65f3cdeca..bad41d0a5 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -73,16 +73,16 @@ bytes ecrecoverCode(bytesConstRef _in) bytes sha256Code(bytesConstRef _in) { - h256 ret; - sha256(_in, bytesRef(ret.data(), 32)); - return ret.asBytes(); + bytes ret(32); + sha256(_in, &ret); + return ret; } bytes ripemd160Code(bytesConstRef _in) { - h256 ret; - ripemd160(_in, bytesRef(ret.data(), 32)); - return ret.asBytes(); + bytes ret(32); + ripemd160(_in, &ret); + return ret; } const std::map State::c_precompiled = @@ -1173,8 +1173,6 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) 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 1 - // TODO: TEST TEST TEST!!! Executive e(*this, _level); if (!e.call(_receiveAddress, _codeAddress, _senderAddress, _value, _gasPrice, _data, io_gas, _originAddress)) { @@ -1185,112 +1183,18 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA e.out().copyTo(_out); return !e.excepted(); -#else -// 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); - if (io_gas < g) - { - io_gas = 0; - return false; - } - - io_gas -= (u256)g; - it->second.exec(_data, _out); - } - else if (addressHasCode(_codeAddress)) - { - auto vm = VMFactory::create(io_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())); - io_sub += evm.sub; - io_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(); - io_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; -#endif } h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256& io_gas, bytesConstRef _code, Address _origin, SubState& io_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(io_gas); - ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, _level); - bytesConstRef out; - - try - { - out = vm->go(evm, _onOp); - io_sub += evm.sub; - io_gas = vm->gas(); - - if (out.size() * c_createDataGas <= io_gas) - io_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); - evm.revert(); - io_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) + Executive e(*this, _level); + if (!e.create(_sender, _endowment, _gasPrice, io_gas, _code, _origin)) { - // 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(); - throw; + e.go(_onOp); + io_sub += e.ext().sub; } - - return newAddress; + io_gas = e.endGas(); + return e.newAddress(); } State State::fromPending(unsigned _i) const From aa25784764e2bb91626bd4d8fc758072b207c5dc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 12 Dec 2014 20:44:36 +0100 Subject: [PATCH 6/6] Fix alignment of RIPEMD160. --- libethereum/State.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index bad41d0a5..7ca973e05 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -82,6 +82,9 @@ bytes ripemd160Code(bytesConstRef _in) { bytes ret(32); ripemd160(_in, &ret); + // leaves the 20-byte hash left-aligned. we want it right-aligned: + memmove(ret.data() + 12, ret.data(), 20); + memset(ret.data(), 0, 12); return ret; }