|
@ -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_precompiledOut = it->second.exec(_data); |
|
|
|
|
|
m_out = &m_precompiledOut; |
|
|
} |
|
|
} |
|
|
m_endGas = (u256)(_gas - g); |
|
|
|
|
|
it->second.exec(_data, bytesRef()); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
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) |
|
|
{ |
|
|
m_endGas -= m_out.size() * c_createDataGas; |
|
|
if (m_out.size() * c_createDataGas <= m_endGas) |
|
|
else |
|
|
m_endGas -= m_out.size() * c_createDataGas; |
|
|
m_out.reset(); |
|
|
else |
|
|
|
|
|
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,25 +205,22 @@ 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()); |
|
|
|
|
|
|
|
|
u256 feesEarned = (m_t.gas() - m_endGas) * m_t.gasPrice(); |
|
|
u256 feesEarned = (m_t.gas() - 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; |
|
|
} |
|
|
} |
|
|