Browse Source

Extensive pathway for reporting transaction execution results.

cl-refactor
Gav Wood 10 years ago
parent
commit
1619d230c3
  1. 7
      alethzero/DappLoader.cpp
  2. 8
      alethzero/MainWin.cpp
  3. 4
      evmjit/libevmjit-cpp/JitVM.cpp
  4. 2
      evmjit/libevmjit/Common.h
  5. 2
      evmjit/libevmjit/Compiler.cpp
  6. 41
      libethereum/Client.cpp
  7. 16
      libethereum/Client.h
  8. 22
      libethereum/Executive.cpp
  9. 8
      libethereum/Executive.h
  10. 6
      libethereum/Interface.h
  11. 57
      libethereum/State.cpp
  12. 14
      libethereum/State.h
  13. 21
      libethereum/Transaction.cpp
  14. 40
      libethereum/Transaction.h
  15. 2
      libevm/VM.h
  16. 2
      libevm/VMFace.h
  17. 2
      mix/ClientModel.cpp
  18. 3
      mix/MachineStates.h
  19. 24
      mix/MixClient.cpp
  20. 3
      mix/MixClient.h
  21. 2
      test/checkRandomStateTest.cpp
  22. 2
      test/createRandomStateTest.cpp
  23. 2
      test/state.cpp

7
alethzero/DappLoader.cpp

@ -72,20 +72,19 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
string32 name = ZeroString32;
QByteArray utf8 = parts[partIndex].toUtf8();
std::copy(utf8.data(), utf8.data() + utf8.size(), name.data());
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("addr(string32)", name)));
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("addr(string32)", name)).output);
domainParts.append(parts[partIndex]);
if (!address)
{
//we have the address of the last part, try to get content hash
contentHash = abiOut<h256>(web3()->ethereum()->call(lastAddress, abiIn("content(string32)", name)));
contentHash = abiOut<h256>(web3()->ethereum()->call(lastAddress, abiIn("content(string32)", name)).output);
if (!contentHash)
throw dev::Exception() << errinfo_comment("Can't resolve address");
}
++partIndex;
}
string32 contentUrl = abiOut<string32>(web3()->ethereum()->call(c_urlHint, abiIn("url(hash256)", contentHash)));
string32 contentUrl = abiOut<string32>(web3()->ethereum()->call(c_urlHint, abiIn("url(hash256)", contentHash)).output);
QString domain = domainParts.join('/');
parts.erase(parts.begin(), parts.begin() + partIndex);
QString path = parts.join('/');

8
alethzero/MainWin.cpp

@ -284,12 +284,12 @@ void Main::installWatches()
Address Main::getNameReg() const
{
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)));
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)).output);
}
Address Main::getCurrencies() const
{
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)));
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output);
}
void Main::installNameRegWatch()
@ -470,7 +470,7 @@ QString Main::pretty(dev::Address _a) const
if (g_newNameReg)
{
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a)))));
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a)).output)));
if (s.size())
return s;
}
@ -575,7 +575,7 @@ Address Main::fromString(QString const& _n) const
auto g_newNameReg = getNameReg();
if (g_newNameReg)
{
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString()))));
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString()))).output);
if (a)
return a;
}

4
evmjit/libevmjit-cpp/JitVM.cpp

@ -69,8 +69,8 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
BOOST_THROW_EXCEPTION(BadJumpDestination());
case ReturnCode::OutOfGas:
BOOST_THROW_EXCEPTION(OutOfGas());
case ReturnCode::StackTooSmall:
BOOST_THROW_EXCEPTION(StackTooSmall());
case ReturnCode::StackUnderflow:
BOOST_THROW_EXCEPTION(StackUnderflow());
case ReturnCode::BadInstruction:
BOOST_THROW_EXCEPTION(BadInstruction());
case ReturnCode::LinkerWorkaround: // never happens

2
evmjit/libevmjit/Common.h

@ -33,7 +33,7 @@ enum class ReturnCode
// Standard error codes
OutOfGas = -1,
StackTooSmall = -2,
StackUnderflow = -2,
BadJumpDestination = -3,
BadInstruction = -4,
Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected

2
evmjit/libevmjit/Compiler.cpp

@ -516,7 +516,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
auto val = stack.pop();
static_cast<void>(val);
// Generate a dummy use of val to make sure that a get(0) will be emitted at this point,
// so that StackTooSmall will be thrown
// so that StackUnderflow will be thrown
// m_builder.CreateICmpEQ(val, val, "dummy");
break;
}

41
libethereum/Client.cpp

@ -491,9 +491,9 @@ void Client::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes
m_tq.attemptImport(t.rlp());
}
bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
ExecutionResult Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
{
bytes out;
ExecutionResult ret;
try
{
u256 n;
@ -505,18 +505,41 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat
n = temp.transactionsFrom(toAddress(_secret));
}
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
u256 gasUsed = temp.execute(m_bc, t.rlp(), &out, false);
(void)gasUsed; // TODO: do something with gasused which it returns.
ret = temp.execute(m_bc, t.rlp(), Permanence::Reverted);
}
catch (...)
{
// TODO: Some sort of notification of failure.
}
return out;
return ret;
}
bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice)
ExecutionResult Client::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
{
ExecutionResult ret;
try
{
u256 n;
State temp;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
{
ReadGuard l(x_stateDB);
temp = asOf(_blockNumber);
n = temp.transactionsFrom(toAddress(_secret));
}
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
ret = temp.execute(m_bc, t.rlp(), Permanence::Reverted);
}
catch (...)
{
// TODO: Some sort of notification of failure.
}
return ret;
}
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice)
{
ExecutionResult ret;
try
{
State temp;
@ -527,16 +550,14 @@ bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u2
}
Executive e(temp, LastHashes(), 0);
if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address()))
{
e.go();
return e.out().toBytes();
}
ret = e.executionResult();
}
catch (...)
{
// TODO: Some sort of notification of failure.
}
return bytes();
return ret;
}
Address Client::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)

16
libethereum/Client.h

@ -212,23 +212,27 @@ public:
void setGasPricer(std::shared_ptr<GasPricer> _gp) { m_gp = _gp; }
/// Submits the given message-call transaction.
virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
/// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through).
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
virtual void inject(bytesConstRef _rlp);
virtual void inject(bytesConstRef _rlp) override;
/// Blocks until all pending transactions have been processed.
virtual void flushTransactions();
virtual void flushTransactions() override;
/// Makes the given call. Nothing is recorded into the state.
virtual bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0);
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) override;
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) override;
/// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH.
virtual bytes call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether);
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether);
// Informational stuff

22
libethereum/Executive.cpp

@ -53,7 +53,16 @@ void Executive::accrueSubState(SubState& _parentContext)
bool Executive::setup(bytesConstRef _rlp)
{
// Entry point for a user-executed transaction.
m_t = Transaction(_rlp, CheckSignature::Sender);
try
{
m_t = Transaction(_rlp, CheckSignature::Sender);
}
catch (...)
{
clog(StateDetail) << "Invalid Signature";
m_excepted = TransactionException::InvalidSignature;
throw;
}
return setup();
}
@ -66,6 +75,7 @@ bool Executive::setup()
if (m_t.nonce() != nonceReq)
{
clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
m_excepted = TransactionException::InvalidNonce;
BOOST_THROW_EXCEPTION(InvalidNonce() << RequirementError((bigint)nonceReq, (bigint)m_t.nonce()));
}
@ -120,7 +130,7 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen
if (_gas < g)
{
m_endGas = 0;
m_excepted = true;
m_excepted = TransactionException::OutOfGasBase;
}
else
{
@ -200,9 +210,15 @@ bool Executive::go(OnOpFunc const& _onOp)
if (m_isCreation)
{
if (m_out.size() * c_createDataGas <= m_endGas)
{
m_codeDeposit = CodeDeposit::Success;
m_endGas -= m_out.size() * c_createDataGas;
}
else
{
m_codeDeposit = CodeDeposit::Failed;
m_out.reset();
}
m_s.m_cache[m_newAddress].setCode(m_out.toBytes());
}
}
@ -214,7 +230,7 @@ bool Executive::go(OnOpFunc const& _onOp)
{
clog(StateSafeExceptions) << "Safe VM Exception. " << diagnostic_information(_e);
m_endGas = 0;
m_excepted = true;
m_excepted = toTransactionException(_e);
m_ext->revert();
}
catch (Exception const& _e)

8
libethereum/Executive.h

@ -101,7 +101,10 @@ public:
/// @returns the new address for the created contract in the CREATE operation.
h160 newAddress() const { return m_newAddress; }
/// @returns true iff the operation ended with a VM exception.
bool excepted() const { return m_excepted; }
bool excepted() const { return m_excepted != TransactionException::None; }
/// Get the above in an amalgamated fashion.
ExecutionResult executionResult() const { return ExecutionResult(gasUsed(), m_excepted, m_newAddress, m_out, m_codeDeposit); }
private:
bool setup();
@ -116,7 +119,8 @@ private:
unsigned m_depth = 0; ///< The context's call-depth.
bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called.
bool m_excepted = false; ///< True if the VM execution resulted in an exception.
CodeDeposit m_codeDeposit = CodeDeposit::None; ///< True if an attempted deposit failed due to lack of gas.
TransactionException m_excepted = TransactionException::None; ///< Details if the VM's execution resulted in an exception.
u256 m_endGas; ///< The final amount of gas for the transaction.
Transaction m_t; ///< The original transaction. Set by setup().

6
libethereum/Interface.h

@ -73,7 +73,11 @@ public:
virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state.
virtual bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) = 0;
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) = 0;
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) = 0;
// [STATE-QUERY API]

57
libethereum/State.cpp

@ -1048,18 +1048,18 @@ LastHashes State::getLastHashes(BlockChain const& _bc, unsigned _n) const
return ret;
}
u256 State::execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output, bool _commit)
ExecutionResult State::execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p)
{
return execute(getLastHashes(_bc, _bc.number()), &_rlp, o_output, _commit);
return execute(getLastHashes(_bc, _bc.number()), &_rlp, _p);
}
u256 State::execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output, bool _commit)
ExecutionResult State::execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p)
{
return execute(getLastHashes(_bc, _bc.number()), _rlp, o_output, _commit);
return execute(getLastHashes(_bc, _bc.number()), _rlp, _p);
}
// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations.
u256 State::execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output, bool _commit)
ExecutionResult State::execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p)
{
#ifndef ETH_RELEASE
commit(); // get an updated hash
@ -1093,41 +1093,38 @@ u256 State::execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output,
ctrace << old.diff(*this);
#endif
if (o_output)
*o_output = e.out().toBytes();
if (!_commit)
{
if (_p == Permanence::Reverted)
m_cache.clear();
return e.gasUsed();
}
commit();
else
{
commit();
#if ETH_PARANOIA && !ETH_FATDB
ctrace << "Executed; now" << rootHash();
ctrace << old.diff(*this);
ctrace << "Executed; now" << rootHash();
ctrace << old.diff(*this);
paranoia("after execution commit.", true);
paranoia("after execution commit.", true);
if (e.t().receiveAddress())
{
EnforceRefs r(m_db, true);
if (storageRoot(e.t().receiveAddress()) && m_db.lookup(storageRoot(e.t().receiveAddress())).empty())
if (e.t().receiveAddress())
{
cwarn << "TRIE immediately after execution; no node for receiveAddress";
BOOST_THROW_EXCEPTION(InvalidTrie());
EnforceRefs r(m_db, true);
if (storageRoot(e.t().receiveAddress()) && m_db.lookup(storageRoot(e.t().receiveAddress())).empty())
{
cwarn << "TRIE immediately after execution; no node for receiveAddress";
BOOST_THROW_EXCEPTION(InvalidTrie());
}
}
}
#endif
// TODO: CHECK TRIE after level DB flush to make sure exactly the same.
// TODO: CHECK TRIE after level DB flush to make sure exactly the same.
// Add to the user-originated transactions that we've executed.
m_transactions.push_back(e.t());
m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs()));
m_transactionSet.insert(e.t().sha3());
}
// Add to the user-originated transactions that we've executed.
m_transactions.push_back(e.t());
m_receipts.push_back(TransactionReceipt(rootHash(), startGasUsed + e.gasUsed(), e.logs()));
m_transactionSet.insert(e.t().sha3());
return e.gasUsed();
return e.executionResult();
}
State State::fromPending(unsigned _i) const

14
libethereum/State.h

@ -84,6 +84,12 @@ protected:
u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return 10 * szabo; }
};
enum class Permanence
{
Reverted,
Committed
};
/**
* @brief Model of the current state of the ledger.
* Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block).
@ -185,10 +191,10 @@ public:
/// Execute a given transaction.
/// This will append @a _t to the transaction list and change the state accordingly.
u256 execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true);
u256 execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true);
u256 execute(LastHashes const& _lh, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(_lh, &_rlp, o_output, _commit); }
u256 execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true);
ExecutionResult execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p = Permanence::Committed);
ExecutionResult execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
ExecutionResult execute(LastHashes const& _lh, bytes const& _rlp, Permanence _p = Permanence::Committed) { return execute(_lh, &_rlp, _p); }
ExecutionResult execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
/// Get the remaining gas limit in this block.
u256 gasLimitRemaining() const { return m_currentBlock.gasLimit - gasUsed(); }

21
libethereum/Transaction.cpp

@ -21,8 +21,10 @@
#include <libdevcore/vector_ref.h>
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/Common.h>
#include <libethcore/Exceptions.h>
#include <libevm/VMFace.h>
#include "Transaction.h"
using namespace std;
using namespace dev;
@ -30,6 +32,25 @@ using namespace dev::eth;
#define ETH_ADDRESS_DEBUG 0
std::ostream& dev::eth::operator<<(std::ostream& _out, ExecutionResult const& _er)
{
_out << "{" << _er.gasUsed << ", " << _er.newAddress << ", " << toHex(_er.output) << "}";
return _out;
}
TransactionException dev::eth::toTransactionException(VMException const& _e)
{
if (!!dynamic_cast<BadInstruction const*>(&_e))
return TransactionException::BadInstruction;
if (!!dynamic_cast<BadJumpDestination const*>(&_e))
return TransactionException::BadJumpDestination;
if (!!dynamic_cast<OutOfGas const*>(&_e))
return TransactionException::OutOfGas;
if (!!dynamic_cast<StackUnderflow const*>(&_e))
return TransactionException::StackUnderflow;
return TransactionException::Unknown;
}
Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig)
{
int field = 0;

40
libethereum/Transaction.h

@ -44,6 +44,46 @@ enum class CheckSignature
Sender
};
enum class TransactionException
{
None = 0,
Unknown,
InvalidSignature,
InvalidNonce,
NotEnoughCash,
OutOfGasBase, ///< Too little gas to pay for the base transaction cost.
BlockGasLimitReached,
BadInstruction,
BadJumpDestination,
OutOfGas, ///< Ran out of gas executing code of the transaction.
StackUnderflow
};
enum class CodeDeposit
{
None = 0,
Failed,
Success
};
class VMException;
TransactionException toTransactionException(VMException const& _e);
/// Description of the result of executing a transaction.
struct ExecutionResult
{
ExecutionResult() = default;
ExecutionResult(u256 _gasUsed, TransactionException _excepted, Address _newAddress, bytesConstRef _output, CodeDeposit _codeDeposit): gasUsed(_gasUsed), excepted(_excepted), newAddress(_newAddress), output(_output.toBytes()), codeDeposit(_codeDeposit) {}
u256 gasUsed;
TransactionException excepted = TransactionException::Unknown;
Address newAddress;
bytes output;
CodeDeposit codeDeposit = CodeDeposit::None;
};
std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er);
/// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class Transaction
{

2
libevm/VM.h

@ -56,7 +56,7 @@ public:
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 require(u256 _n) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } }
void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
u256 curPC() const { return m_curPC; }

2
libevm/VMFace.h

@ -31,7 +31,7 @@ struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {};
struct BadJumpDestination: virtual VMException {};
struct OutOfGas: virtual VMException {};
struct StackTooSmall: virtual VMException {};
struct StackUnderflow: virtual VMException {};
/// EVM Virtual Machine interface
class VMFace

2
mix/ClientModel.cpp

@ -534,7 +534,7 @@ void ClientModel::onNewTransaction()
{
function = funcDef->name();
ContractCallDataEncoder encoder;
QStringList returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue);
QStringList returnValues = encoder.decode(funcDef->returnParameters(), tr.result.output);
returned += "(";
returned += returnValues.join(", ");
returned += ")";

3
mix/MachineStates.h

@ -29,6 +29,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include <libdevcore/Common.h>
#include <libdevcrypto/Common.h>
#include <libevmcore/Instruction.h>
#include <libethereum/Transaction.h>
#include <libethereum/TransactionReceipt.h>
namespace dev
@ -74,7 +75,7 @@ namespace mix
std::vector<MachineState> machineStates;
std::vector<bytes> transactionData;
std::vector<MachineCode> executionCode;
bytes returnValue;
dev::eth::ExecutionResult result;
dev::Address address;
dev::Address sender;
dev::Address contractAddress;

24
mix/MixClient.cpp

@ -175,7 +175,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
execution.finalize();
ExecutionResult d;
d.returnValue = execution.out().toVector();
d.result = execution.executionResult();
d.machineStates = machineStates;
d.executionCode = std::move(codes);
d.transactionData = std::move(data);
@ -191,7 +191,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
// execute on a state
if (!_call)
{
_state.execute(lastHashes, rlp, nullptr, true);
_state.execute(lastHashes, rlp);
// collect watches
h256Set changed;
Guard l(m_filterLock);
@ -276,7 +276,7 @@ void MixClient::flushTransactions()
{
}
bytes MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
{
u256 n;
State temp;
@ -289,7 +289,23 @@ bytes MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _
bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true);
return lastExecution().returnValue;
return lastExecution().result;
}
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
{
u256 n;
State temp;
{
ReadGuard lr(x_state);
temp = asOf(_blockNumber);
n = temp.transactionsFrom(toAddress(_secret));
}
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true);
return lastExecution().result;
}
u256 MixClient::balanceAt(Address _a, int _block) const

3
mix/MixClient.h

@ -52,7 +52,8 @@ public:
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override;
void inject(bytesConstRef _rlp) override;
void flushTransactions() override;
bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber) override;
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber) override;
dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber) override;
u256 balanceAt(Address _a, int _block) const override;
u256 countAt(Address _a, int _block) const override;
u256 stateAt(Address _a, u256 _l, int _block) const override;

2
test/checkRandomStateTest.cpp

@ -87,7 +87,7 @@ bool doStateTest(mValue& _v)
try
{
theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
}
catch (Exception const& _e)
{

2
test/createRandomStateTest.cpp

@ -162,7 +162,7 @@ void doStateTests(json_spirit::mValue& _v)
try
{
theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output);
output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx).output;
}
catch (Exception const& _e)
{

2
test/state.cpp

@ -63,7 +63,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
try
{
Listener::ExecTimeGuard guard{i.first};
theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
}
catch (Exception const& _e)
{

Loading…
Cancel
Save