Browse Source

Merge branch 'develop' into p2p

cl-refactor
subtly 10 years ago
parent
commit
2cc5d2b3d6
  1. 10
      CMakeLists.txt
  2. 2
      cmake/EthDependencies.cmake
  3. 2
      evmjit/libevmjit/ExecutionEngine.cpp
  4. 12
      libdevcore/Exceptions.h
  5. 8
      libdevcore/RLP.h
  6. 6
      libdevcore/vector_ref.h
  7. 2
      libdevcrypto/ECDHE.h
  8. 60
      libethcore/CommonEth.cpp
  9. 8
      libethcore/Exceptions.h
  10. 6
      libethereum/BlockDetails.h
  11. 2
      libevm/VM.cpp
  12. 2
      libevmcore/Assembly.cpp
  13. 4
      libevmcore/Assembly.h
  14. 4
      liblll/Parser.cpp
  15. 6
      libp2p/Common.h
  16. 2
      libsolidity/Exceptions.h
  17. 11
      libweb3jsonrpc/CMakeLists.txt
  18. 25
      mix/ClientModel.cpp
  19. 32
      mix/ClientModel.h
  20. 2
      mix/CodeHighlighter.h
  21. 8
      mix/Exceptions.h
  22. 8
      mix/MachineStates.h
  23. 73
      mix/MixClient.cpp
  24. 8
      mix/MixClient.h
  25. 31
      mix/qml/CallStack.qml
  26. 1
      mix/qml/DebugInfoList.qml
  27. 41
      mix/qml/TransactionLog.qml
  28. 10
      mix/qml/main.qml
  29. 1
      mix/res.qrc
  30. 7
      test/CMakeLists.txt
  31. 4
      test/natspec.cpp
  32. 36
      test/webthreestubclient.h

10
CMakeLists.txt

@ -43,6 +43,10 @@ function(configureProject)
if (EVMJIT)
add_definitions(-DETH_EVMJIT)
endif()
if (HEADLESS)
add_definitions(-DETH_HEADLESS)
endif()
endfunction()
@ -65,13 +69,13 @@ function(createBuildInfo)
endif ()
if (EVMJIT)
set(ETH_BUILD_PLATFORM "${TARGET_PLATFORM}/JIT")
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/JIT")
else ()
set(ETH_BUILD_PLATFORM "${TARGET_PLATFORM}/int")
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int")
endif ()
if (PARANOIA)
set(ETH_BUILD_PLATFORM "${TARGET_PLATFORM}/PARA")
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA")
endif ()
#cmake build type may be not specified when using msvc

2
cmake/EthDependencies.cmake

@ -122,6 +122,8 @@ if (NOT HEADLESS)
string(REGEX REPLACE "npm" "" ETH_NPM_DIRECTORY ${ETH_NPM})
message(" - npm location : ${ETH_NPM}")
find_program(ETH_JSON_RPC_STUB jsonrpcstub)
endif() #HEADLESS
# use multithreaded boost libraries, with -mt suffix

2
evmjit/libevmjit/ExecutionEngine.cpp

@ -29,7 +29,7 @@ namespace jit
namespace
{
typedef ReturnCode(*EntryFuncPtr)(Runtime*);
using EntryFuncPtr = ReturnCode(*)(Runtime*);
ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
{

12
libdevcore/Exceptions.h

@ -44,10 +44,10 @@ struct FileError: virtual Exception {};
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): m_f("Interface " + _f + " not supported.") {} virtual const char* what() const noexcept { return m_f.c_str(); } private: std::string m_f; };
// error information to be added to exceptions
typedef boost::error_info<struct tag_invalidSymbol, char> errinfo_invalidSymbol;
typedef boost::error_info<struct tag_address, std::string> errinfo_wrongAddress;
typedef boost::error_info<struct tag_comment, std::string> errinfo_comment;
typedef boost::error_info<struct tag_required, bigint> errinfo_required;
typedef boost::error_info<struct tag_got, bigint> errinfo_got;
typedef boost::tuple<errinfo_required, errinfo_got> RequirementError;
using errinfo_invalidSymbol = boost::error_info<struct tag_invalidSymbol, char>;
using errinfo_wrongAddress = boost::error_info<struct tag_address, std::string>;
using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
using errinfo_required = boost::error_info<struct tag_required, bigint>;
using errinfo_got = boost::error_info<struct tag_got, bigint>;
using RequirementError = boost::tuple<errinfo_required, errinfo_got>;
}

8
libdevcore/RLP.h

@ -37,7 +37,7 @@ namespace dev
{
class RLP;
typedef std::vector<RLP> RLPs;
using RLPs = std::vector<RLP>;
template <class _T> struct intTraits { static const unsigned maxSize = sizeof(_T); };
template <> struct intTraits<u160> { static const unsigned maxSize = 20; };
@ -125,7 +125,7 @@ public:
/// @note if used to access items in ascending order, this is efficient.
RLP operator[](unsigned _i) const;
typedef RLP element_type;
using element_type = RLP;
/// @brief Iterator class for iterating through items of RLP list.
class iterator
@ -133,8 +133,8 @@ public:
friend class RLP;
public:
typedef RLP value_type;
typedef RLP element_type;
using value_type = RLP;
using element_type = RLP;
iterator& operator++();
iterator operator++(int) { auto ret = *this; operator++(); return ret; }

6
libdevcore/vector_ref.h

@ -12,9 +12,9 @@ template <class _T>
class vector_ref
{
public:
typedef _T value_type;
typedef _T element_type;
typedef typename std::conditional<std::is_const<_T>::value, typename std::remove_const<_T>::type, _T>::type mutable_value_type;
using value_type = _T;
using element_type = _T;
using mutable_value_type = typename std::conditional<std::is_const<_T>::value, typename std::remove_const<_T>::type, _T>::type;
vector_ref(): m_data(nullptr), m_count(0) {}
vector_ref(_T* _data, size_t _count): m_data(_data), m_count(_count) {}

2
libdevcrypto/ECDHE.h

@ -31,7 +31,7 @@ namespace crypto
{
/// Public key of remote and corresponding shared secret.
typedef std::pair<Public,h256> AliasSession;
using AliasSession = std::pair<Public,h256>;
/**
* @brief An addressable EC key pair.

60
libethcore/CommonEth.cpp

@ -35,32 +35,42 @@ namespace eth
const unsigned c_protocolVersion = 53;
const unsigned c_databaseVersion = 5;
static const vector<pair<u256, string>> g_units =
template <size_t n> constexpr u256 exp10()
{
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Uether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Vether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Dether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Nether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Yether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Zether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000000, "Eether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000, "Pether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000, "Tether"},
{(u256(1000000000) * 1000000000) * 1000000000, "Gether"},
{(u256(1000000000) * 1000000000) * 1000000, "Mether"},
{(u256(1000000000) * 1000000000) * 1000, "grand"},
{u256(1000000000) * 1000000000, "ether"},
{u256(1000000000) * 1000000, "finney"},
{u256(1000000000) * 1000, "szabo"},
{u256(1000000000), "Gwei"},
{u256(1000000), "Mwei"},
{u256(1000), "Kwei"},
{u256(1), "wei"}
};
return exp10<n - 1>() * u256(10);
}
template <> constexpr u256 exp10<0>()
{
return u256(1);
}
vector<pair<u256, string>> const& units()
{
return g_units;
static const vector<pair<u256, string>> s_units =
{
{exp10<54>(), "Uether"},
{exp10<51>(), "Vether"},
{exp10<48>(), "Dether"},
{exp10<45>(), "Nether"},
{exp10<42>(), "Yether"},
{exp10<39>(), "Zether"},
{exp10<36>(), "Eether"},
{exp10<33>(), "Pether"},
{exp10<30>(), "Tether"},
{exp10<27>(), "Gether"},
{exp10<24>(), "Mether"},
{exp10<21>(), "grand"},
{exp10<18>(), "ether"},
{exp10<15>(), "finney"},
{exp10<12>(), "szabo"},
{exp10<9>(), "Gwei"},
{exp10<6>(), "Mwei"},
{exp10<3>(), "Kwei"},
{exp10<0>(), "wei"}
};
return s_units;
}
std::string formatBalance(bigint const& _b)
@ -75,13 +85,13 @@ std::string formatBalance(bigint const& _b)
else
b = (u256)_b;
if (b > g_units[0].first * 10000)
if (b > units()[0].first * 10000)
{
ret << (b / g_units[0].first) << " " << g_units[0].second;
ret << (b / units()[0].first) << " " << units()[0].second;
return ret.str();
}
ret << setprecision(5);
for (auto const& i: g_units)
for (auto const& i: units())
if (i.first != 1 && b >= i.first * 100)
{
ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second;

8
libethcore/Exceptions.h

@ -29,10 +29,10 @@ namespace eth
{
// information to add to exceptions
typedef boost::error_info<struct tag_field, std::string> errinfo_name;
typedef boost::error_info<struct tag_field, int> errinfo_field;
typedef boost::error_info<struct tag_data, std::string> errinfo_data;
typedef boost::tuple<errinfo_field, errinfo_data> BadFieldError;
using errinfo_name = boost::error_info<struct tag_field, std::string>;
using errinfo_field = boost::error_info<struct tag_field, int>;
using errinfo_data = boost::error_info<struct tag_data, std::string>;
using BadFieldError = boost::tuple<errinfo_field, errinfo_data>;
struct DatabaseAlreadyOpen: virtual dev::Exception {};
struct NotEnoughCash: virtual dev::Exception {};

6
libethereum/BlockDetails.h

@ -70,9 +70,9 @@ struct BlockReceipts
TransactionReceipts receipts;
};
typedef std::map<h256, BlockDetails> BlockDetailsHash;
typedef std::map<h256, BlockLogBlooms> BlockLogBloomsHash;
typedef std::map<h256, BlockReceipts> BlockReceiptsHash;
using BlockDetailsHash = std::map<h256, BlockDetails>;
using BlockLogBloomsHash = std::map<h256, BlockLogBlooms>;
using BlockReceiptsHash = std::map<h256, BlockReceipts>;
static const BlockDetails NullBlockDetails;
static const BlockLogBlooms NullBlockLogBlooms;

2
libevm/VM.cpp

@ -354,7 +354,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
auto base = m_stack.back();
auto expon = m_stack[m_stack.size() - 2];
m_stack.pop_back();
m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256);
m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(1) << 256);
break;
}
case Instruction::NOT:

2
libevmcore/Assembly.cpp

@ -291,7 +291,7 @@ Assembly& Assembly::optimise(bool _enable)
{ Instruction::SDIV, [](u256 a, u256 b)->u256{return s2u(u2s(a) / u2s(b));} },
{ Instruction::MOD, [](u256 a, u256 b)->u256{return a % b;} },
{ Instruction::SMOD, [](u256 a, u256 b)->u256{return s2u(u2s(a) % u2s(b));} },
{ Instruction::EXP, [](u256 a, u256 b)->u256{return (u256)boost::multiprecision::powm((bigint)a, (bigint)b, bigint(2) << 256);} },
{ Instruction::EXP, [](u256 a, u256 b)->u256{return (u256)boost::multiprecision::powm((bigint)a, (bigint)b, bigint(1) << 256);} },
{ Instruction::SIGNEXTEND, signextend },
{ Instruction::LT, [](u256 a, u256 b)->u256{return a < b ? 1 : 0;} },
{ Instruction::GT, [](u256 a, u256 b)->u256{return a > b ? 1 : 0;} },

4
libevmcore/Assembly.h

@ -63,8 +63,8 @@ private:
u256 m_data;
};
typedef std::vector<AssemblyItem> AssemblyItems;
typedef vector_ref<AssemblyItem const> AssemblyItemsConstRef;
using AssemblyItems = std::vector<AssemblyItem>;
using AssemblyItemsConstRef = vector_ref<AssemblyItem const>;
std::ostream& operator<<(std::ostream& _out, AssemblyItemsConstRef _i);
inline std::ostream& operator<<(std::ostream& _out, AssemblyItems const& _i) { return operator<<(_out, AssemblyItemsConstRef(&_i)); }

4
liblll/Parser.cpp

@ -89,8 +89,8 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out)
using qi::standard::space;
using qi::standard::space_type;
using dev::eth::parseTreeLLL_::tagNode;
typedef sp::basic_string<std::string, sp::utree_type::symbol_type> symbol_type;
typedef string::const_iterator it;
using symbol_type = sp::basic_string<std::string, sp::utree_type::symbol_type>;
using it = string::const_iterator;
static const u256 ether = u256(1000000000) * 1000000000;
static const u256 finney = u256(1000000000) * 1000000;

6
libp2p/Common.h

@ -115,9 +115,9 @@ inline bool isPermanentProblem(DisconnectReason _r)
/// @returns the string form of the given disconnection reason.
std::string reasonOf(DisconnectReason _r);
typedef std::pair<std::string, u256> CapDesc;
typedef std::set<CapDesc> CapDescSet;
typedef std::vector<CapDesc> CapDescs;
using CapDesc = std::pair<std::string, u256>;
using CapDescSet = std::set<CapDesc>;
using CapDescs = std::vector<CapDesc>;
/*
* Used by Host to pass negotiated information about a connection to a

2
libsolidity/Exceptions.h

@ -38,7 +38,7 @@ struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
struct DocstringParsingError: virtual Exception {};
typedef boost::error_info<struct tag_sourceLocation, Location> errinfo_sourceLocation;
using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, Location>;
}
}

11
libweb3jsonrpc/CMakeLists.txt

@ -32,6 +32,17 @@ target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} solidity)
target_link_libraries(${EXECUTABLE} serpent)
if (ETH_JSON_RPC_STUB)
add_custom_target(jsonrpcstub)
add_custom_command(TARGET jsonrpcstub
POST_BUILD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${ETH_JSON_RPC_STUB} spec.json --cpp-server=AbstractWebThreeStubServer --cpp-client=WebThreeStubClient
COMMAND cmake -E rename webthreestubclient.h ../test/webthreestubclient.h
)
add_dependencies(${EXECUTABLE} jsonrpcstub)
endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

25
mix/ClientModel.cpp

@ -82,7 +82,7 @@ ClientModel::ClientModel(AppContext* _context):
qRegisterMetaType<QInstruction*>("QInstruction");
qRegisterMetaType<QCode*>("QCode");
qRegisterMetaType<QCallData*>("QCallData");
qRegisterMetaType<TransactionLogEntry*>("TransactionLogEntry");
qRegisterMetaType<RecordLogEntry*>("RecordLogEntry");
connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection);
m_client.reset(new MixClient(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString()));
@ -313,10 +313,10 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
}
void ClientModel::debugTransaction(unsigned _block, unsigned _index)
void ClientModel::debugRecord(unsigned _index)
{
auto const& t = m_client->execution(_block, _index);
showDebuggerForTransaction(t);
ExecutionResult const& e = m_client->executions().at(_index);
showDebuggerForTransaction(e);
}
void ClientModel::showDebugError(QString const& _error)
@ -346,9 +346,10 @@ void ClientModel::onStateReset()
void ClientModel::onNewTransaction()
{
unsigned block = m_client->number() + 1;
unsigned index = m_client->pendingExecutions().size() - 1;
ExecutionResult const& tr = m_client->lastExecution();
unsigned block = m_client->number() + 1;
unsigned recordIndex = m_client->executions().size() - 1;
QString transactionIndex = tr.isCall() ? QObject::tr("Call") : QString("%1:%2").arg(block).arg(tr.transactionIndex);
QString address = QString::fromStdString(toJS(tr.address));
QString value = QString::fromStdString(dev::toString(tr.value));
QString contract = address;
@ -359,7 +360,7 @@ void ClientModel::onNewTransaction()
//TODO: handle value transfer
FixedHash<4> functionHash;
bool call = false;
bool abi = false;
if (creation)
{
//contract creation
@ -374,12 +375,12 @@ void ClientModel::onNewTransaction()
}
else
{
//call
//transaction/call
if (tr.transactionData.size() > 0 && tr.transactionData.front().size() >= 4)
{
functionHash = FixedHash<4>(tr.transactionData.front().data(), FixedHash<4>::ConstructFromPointer);
function = QString::fromStdString(toJS(functionHash));
call = true;
abi = true;
}
else
function = QObject::tr("<none>");
@ -393,7 +394,7 @@ void ClientModel::onNewTransaction()
auto compilerRes = m_context->codeModel()->code();
QContractDefinition* def = compilerRes->contract();
contract = def->name();
if (call)
if (abi)
{
QFunctionDefinition* funcDef = def->getFunction(functionHash);
if (funcDef)
@ -407,9 +408,9 @@ void ClientModel::onNewTransaction()
}
}
TransactionLogEntry* log = new TransactionLogEntry(block, index, contract, function, value, address, returned);
RecordLogEntry* log = new RecordLogEntry(recordIndex, transactionIndex, contract, function, value, address, returned, tr.isCall());
QQmlEngine::setObjectOwnership(log, QQmlEngine::JavaScriptOwnership);
emit newTransaction(log);
emit newRecord(log);
}
}

32
mix/ClientModel.h

@ -69,13 +69,13 @@ struct TransactionSettings
/// UI Transaction log record
class TransactionLogEntry: public QObject
class RecordLogEntry: public QObject
{
Q_OBJECT
/// Transaction block number
Q_PROPERTY(unsigned block MEMBER m_block CONSTANT)
/// Transaction index within the block
Q_PROPERTY(unsigned tindex MEMBER m_index CONSTANT)
/// Recording index
Q_PROPERTY(unsigned recordIndex MEMBER m_recordIndex CONSTANT)
/// Human readable transaction bloack and transaction index
Q_PROPERTY(QString transactionIndex MEMBER m_transactionIndex CONSTANT)
/// Contract name if any
Q_PROPERTY(QString contract MEMBER m_contract CONSTANT)
/// Function name if any
@ -86,21 +86,25 @@ class TransactionLogEntry: public QObject
Q_PROPERTY(QString address MEMBER m_address CONSTANT)
/// Returned value or transaction address in case of creation
Q_PROPERTY(QString returned MEMBER m_returned CONSTANT)
/// true if call, false if transaction
Q_PROPERTY(bool call MEMBER m_call CONSTANT)
public:
TransactionLogEntry():
m_block(0), m_index(0) {}
TransactionLogEntry(int _block, int _index, QString _contract, QString _function, QString _value, QString _address, QString _returned):
m_block(_block), m_index(_index), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned) {}
RecordLogEntry():
m_recordIndex(0), m_call(false) {}
RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call):
m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call) {}
private:
unsigned m_block;
unsigned m_index;
unsigned m_recordIndex;
QString m_transactionIndex;
QString m_contract;
QString m_function;
QString m_value;
QString m_address;
QString m_returned;
bool m_call;
};
/**
@ -133,8 +137,8 @@ public slots:
/// Setup state, run transaction sequence, show debugger for the last transaction
/// @param _state JS object with state configuration
void setupState(QVariantMap _state);
/// Show the debugger for a specified transaction
Q_INVOKABLE void debugTransaction(unsigned _block, unsigned _index);
/// Show the debugger for a specified record
Q_INVOKABLE void debugRecord(unsigned _index);
private slots:
/// Update UI with machine states result. Display a modal dialog.
@ -168,7 +172,7 @@ signals:
/// @param _message RPC response in Json format
void apiResponse(QString const& _message);
/// New transaction log entry
void newTransaction(TransactionLogEntry* _tr);
void newRecord(RecordLogEntry* _r);
/// State (transaction log) cleared
void stateCleared();

2
mix/CodeHighlighter.h

@ -81,7 +81,7 @@ public:
int start;
int length;
};
typedef std::vector<FormatRange> Formats; // Sorted by start position
using Formats = std::vector<FormatRange>; // Sorted by start position
public:
/// Collect highligting information by lexing the source

8
mix/Exceptions.h

@ -40,10 +40,10 @@ struct FunctionNotFoundException: virtual Exception {};
struct ExecutionStateException: virtual Exception {};
struct ParameterChangedException: virtual Exception {};
typedef boost::error_info<struct tagQmlError, QQmlError> QmlErrorInfo;
typedef boost::error_info<struct tagFileError, std::string> FileError;
typedef boost::error_info<struct tagBlockIndex, unsigned> BlockIndex;
typedef boost::error_info<struct tagFunctionName, std::string> FunctionName;
using QmlErrorInfo = boost::error_info<struct tagQmlError, QQmlError>;
using FileError = boost::error_info<struct tagFileError, std::string>;
using BlockIndex = boost::error_info<struct tagBlockIndex, unsigned>;
using FunctionName = boost::error_info<struct tagFunctionName, std::string>;
}
}

8
mix/MachineStates.h

@ -61,7 +61,7 @@ namespace mix
*/
struct ExecutionResult
{
ExecutionResult() : receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {}
ExecutionResult(): transactionIndex(std::numeric_limits<unsigned>::max()) {}
std::vector<MachineState> machineStates;
std::vector<bytes> transactionData;
@ -71,9 +71,11 @@ namespace mix
dev::Address sender;
dev::Address contractAddress;
dev::u256 value;
dev::eth::TransactionReceipt receipt;
unsigned transactionIndex;
bool isCall() const { return transactionIndex == std::numeric_limits<unsigned>::max(); }
};
using ExecutionResults = std::vector<ExecutionResult>;
}
}
}

73
mix/MixClient.cpp

@ -15,7 +15,6 @@
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MixClient.cpp
* @author Yann yann@ethdev.com
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
@ -90,11 +89,10 @@ void MixClient::resetState(u256 _balance)
m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty);
m_state.sync(bc());
m_startState = m_state;
m_pendingExecutions.clear();
m_executions.clear();
}
void MixClient::executeTransaction(Transaction const& _t, State& _state)
void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call)
{
bytes rlp = _t.rlp();
@ -171,30 +169,33 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
d.value = _t.value();
if (_t.isCreation())
d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce())));
d.receipt = TransactionReceipt(execState.rootHash(), execution.gasUsed(), execution.logs()); //TODO: track gas usage
m_pendingExecutions.emplace_back(std::move(d));
if (!_call)
d.transactionIndex = m_state.pending().size();
m_executions.emplace_back(std::move(d));
// execute on a state
_state.execute(lastHashes, rlp, nullptr, true);
// collect watches
h256Set changed;
Guard l(m_filterLock);
for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() > bc().number())
{
// acceptable number.
auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1));
if (m.size())
if (!_call)
{
_state.execute(lastHashes, rlp, nullptr, true);
// collect watches
h256Set changed;
Guard l(m_filterLock);
for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() > bc().number())
{
// filter catches them
for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, bc().number() + 1));
changed.insert(i.first);
// acceptable number.
auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1));
if (m.size())
{
// filter catches them
for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, bc().number() + 1));
changed.insert(i.first);
}
}
}
changed.insert(dev::eth::PendingChangedFilter);
noteChanged(changed);
changed.insert(dev::eth::PendingChangedFilter);
noteChanged(changed);
}
}
void MixClient::mine()
@ -206,28 +207,18 @@ void MixClient::mine()
bc().import(m_state.blockData(), m_stateDB);
m_state.sync(bc());
m_startState = m_state;
m_executions.emplace_back(std::move(m_pendingExecutions));
h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter };
noteChanged(changed);
}
ExecutionResult const& MixClient::execution(unsigned _block, unsigned _transaction) const
{
if (_block == bc().number() + 1)
return m_pendingExecutions.at(_transaction);
return m_executions.at(_block - 1).at(_transaction);
}
ExecutionResult const& MixClient::lastExecution() const
{
if (m_pendingExecutions.size() > 0)
return m_pendingExecutions.back();
return m_executions.back().back();
return m_executions.back();
}
ExecutionResults const& MixClient::pendingExecutions() const
ExecutionResults const& MixClient::executions() const
{
return m_pendingExecutions;
return m_executions;
}
State MixClient::asOf(int _block) const
@ -246,7 +237,7 @@ void MixClient::transact(Secret _secret, u256 _value, Address _dest, bytes const
WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
executeTransaction(t, m_state);
executeTransaction(t, m_state, false);
}
Address MixClient::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
@ -254,7 +245,7 @@ Address MixClient::transact(Secret _secret, u256 _endowment, bytes const& _init,
WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret));
eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret);
executeTransaction(t, m_state);
executeTransaction(t, m_state, false);
Address address = right160(sha3(rlpList(t.sender(), t.nonce())));
return address;
}
@ -263,7 +254,7 @@ void MixClient::inject(bytesConstRef _rlp)
{
WriteGuard l(x_state);
eth::Transaction t(_rlp, CheckSignature::None);
executeTransaction(t, m_state);
executeTransaction(t, m_state, false);
}
void MixClient::flushTransactions()
@ -282,8 +273,8 @@ bytes MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp);
return m_pendingExecutions.back().returnValue;
executeTransaction(t, temp, true);
return lastExecution().returnValue;
}
u256 MixClient::balanceAt(Address _a, int _block) const

8
mix/MixClient.h

@ -45,9 +45,8 @@ public:
void resetState(u256 _balance);
KeyPair const& userAccount() const { return m_userAccount; }
void mine();
ExecutionResult const& execution(unsigned _block, unsigned _transaction) const;
ExecutionResult const& lastExecution() const;
ExecutionResults const& pendingExecutions() const;
ExecutionResults const& executions() const;
//dev::eth::Interface
void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override;
@ -90,7 +89,7 @@ public:
bool submitNonce(h256 const&) override { return false; }
private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call);
void noteChanged(h256Set const& _filters);
dev::eth::State asOf(int _block) const;
MixBlockChain& bc() { return *m_bc; }
@ -105,8 +104,7 @@ private:
mutable std::mutex m_filterLock;
std::map<h256, dev::eth::InstalledFilter> m_filters;
std::map<unsigned, dev::eth::ClientWatch> m_watches;
std::vector<ExecutionResults> m_executions;
ExecutionResults m_pendingExecutions;
ExecutionResults m_executions;
std::string m_dbPath;
unsigned m_minigThreads;
};

31
mix/qml/CallStack.qml

@ -1,31 +0,0 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
Item {
property alias model: callTable.model
signal frameActivated(int index)
ColumnLayout {
anchors.fill: parent
Text {
text: qsTr("Call Stack")
Layout.fillWidth: true
}
TableView {
id: callTable
Layout.fillWidth: true
Layout.fillHeight: true
headerDelegate: null
TableViewColumn {
role: "modelData"
title: qsTr("Address")
width: parent.width
}
onActivated: {
frameActivated(row);
}
}
}
}

1
mix/qml/DebugInfoList.qml

@ -115,6 +115,7 @@ ColumnLayout {
//storageContainer.state = "";
}
}
onActivated: rowActivated(row);
TableViewColumn {
role: "modelData"
width: parent.width

41
mix/qml/TransactionLog.qml

@ -5,6 +5,14 @@ import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
Item {
property bool showLogs: true
property ListModel fullModel: ListModel{}
property ListModel transactionModel: ListModel{}
onShowLogsChanged: {
logTable.model = showLogs ? fullModel : transactionModel
}
Action {
id: addStateAction
text: "Add State"
@ -70,17 +78,13 @@ Item {
}
}
TableView {
id: logTable
Layout.fillWidth: true
Layout.fillHeight: true
model: logModel
model: fullModel
TableViewColumn {
role: "block"
title: qsTr("Block")
width: 40
}
TableViewColumn {
role: "tindex"
role: "transactionIndex"
title: qsTr("Index")
width: 40
}
@ -110,30 +114,31 @@ Item {
width: 120
}
onActivated: {
var item = logModel.get(row);
clientModel.debugTransaction(item.block, item.tindex);
var item = logTable.model.get(row);
clientModel.debugRecord(item.recordIndex);
}
Keys.onPressed: {
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < logModel.count) {
var item = logModel.get(currentRow);
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < logTable.model.count) {
var item = logTable.model.get(currentRow);
appContext.toClipboard(item.returned);
}
}
}
}
ListModel {
id: logModel
}
Connections {
target: clientModel
onStateCleared: {
logModel.clear();
fullModel.clear();
transactionModel.clear();
}
onNewTransaction: {
onNewRecord: {
if (recording.checked)
logModel.append(_tr);
{
fullModel.append(_r);
if (!_r.call)
transactionModel.append(_r);
}
}
}

10
mix/qml/main.qml

@ -54,6 +54,7 @@ ApplicationWindow {
MenuItem { action: toggleTransactionLogAction }
MenuItem { action: toggleWebPreviewAction }
MenuItem { action: toggleWebPreviewOrientationAction }
MenuItem { action: toggleCallsInLog }
}
}
@ -162,6 +163,15 @@ ApplicationWindow {
onTriggered: mainContent.toggleWebPreviewOrientation();
}
Action {
id: toggleCallsInLog
text: qsTr("Show Calls in Transaction Log")
shortcut: ""
checkable: true
checked: mainContent.rightPane.transactionLog.showLogs
onTriggered: mainContent.rightPane.transactionLog.showLogs = !mainContent.rightPane.transactionLog.showLogs
}
Action {
id: toggleRunOnLoadAction
text: qsTr("Load State on Startup")

1
mix/res.qrc

@ -61,7 +61,6 @@
<file>stdc/std.sol</file>
<file>qml/TransactionLog.qml</file>
<file>res/mix_256x256x32.png</file>
<file>qml/CallStack.qml</file>
<file>qml/QVariableDeclaration.qml</file>
<file>qml/Style.qml</file>
<file>qml/qmldir</file>

7
test/CMakeLists.txt

@ -21,9 +21,10 @@ target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore)
target_link_libraries(testeth secp256k1)
target_link_libraries(testeth solidity)
target_link_libraries(testeth webthree)
target_link_libraries(testeth natspec)
if (NOT HEADLESS)
target_link_libraries(testeth webthree)
target_link_libraries(testeth natspec)
endif()
if (JSONRPC)
target_link_libraries(testeth web3jsonrpc)
target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES})

4
test/natspec.cpp

@ -19,6 +19,8 @@
* @date 2015
*/
#if !ETH_HEADLESS
#include <boost/test/unit_test.hpp>
#include <libdevcore/Log.h>
#include <libnatspec/NatspecExpressionEvaluator.h>
@ -110,3 +112,5 @@ BOOST_AUTO_TEST_CASE(natspec_js_eval_error)
}
BOOST_AUTO_TEST_SUITE_END()
#endif

36
test/webthreestubclient.h

@ -213,6 +213,16 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_flush() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_flush",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
@ -347,13 +357,13 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_changed(const int& param1) throw (jsonrpc::JsonRpcException)
Json::Value eth_changed(const int& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_changed",p);
if (result.isBool())
return result.asBool();
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
@ -377,6 +387,26 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getWork",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_submitWork(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_submitWork",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{
Json::Value p;

Loading…
Cancel
Save