From f990a1ac632d6ff0067e8e14cdd234f49f0a54db Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 10:17:42 +0100 Subject: [PATCH 01/20] mix IDE M1 first commit --- mix/ApplicationCtx.cpp | 62 +++++++- mix/ApplicationCtx.h | 19 ++- mix/AssemblyDebuggerCtrl.cpp | 84 +++++++++++ mix/AssemblyDebuggerCtrl.h | 55 +++++++ mix/AssemblyDebuggerModel.cpp | 111 ++++++++++++++ mix/AssemblyDebuggerModel.h | 49 ++++++ mix/CodeEditorExtensionManager.cpp | 22 ++- mix/CodeEditorExtensionManager.h | 3 +- mix/ConstantCompilationCtrl.cpp | 4 +- mix/ConstantCompilationModel.cpp | 1 + mix/ConstantCompilationModel.h | 2 + mix/DebuggingStateWrapper.cpp | 189 +++++++++++++++++++++++ mix/DebuggingStateWrapper.h | 133 +++++++++++++++++ mix/Extension.cpp | 29 +++- mix/Extension.h | 14 +- mix/KeyEventManager.cpp | 43 ++++++ mix/KeyEventManager.h | 42 ++++++ mix/TransactionBuilder.cpp | 92 ++++++++++++ mix/TransactionBuilder.h | 48 ++++++ mix/main.cpp | 3 + mix/qml.qrc | 3 + mix/qml/BasicMessage.qml | 20 +++ mix/qml/Debugger.qml | 231 +++++++++++++++++++++++++++++ mix/qml/MainContent.qml | 24 ++- mix/qml/js/Debugger.js | 63 ++++++++ mix/qml/main.qml | 40 ++++- 26 files changed, 1353 insertions(+), 33 deletions(-) create mode 100644 mix/AssemblyDebuggerCtrl.cpp create mode 100644 mix/AssemblyDebuggerCtrl.h create mode 100644 mix/AssemblyDebuggerModel.cpp create mode 100644 mix/AssemblyDebuggerModel.h create mode 100644 mix/DebuggingStateWrapper.cpp create mode 100644 mix/DebuggingStateWrapper.h create mode 100644 mix/KeyEventManager.cpp create mode 100644 mix/KeyEventManager.h create mode 100644 mix/TransactionBuilder.cpp create mode 100644 mix/TransactionBuilder.h create mode 100644 mix/qml/BasicMessage.qml create mode 100644 mix/qml/Debugger.qml create mode 100644 mix/qml/js/Debugger.js diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index f97478f3c..52e66dab7 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -14,23 +14,83 @@ /** @file ApplicationCtx.cpp * @author Yann yann@ethdev.com * @date 2014 - * Provide an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. + * For now ApplicationCtx provides reference to: + * - QQmlApplicationEngine + * - dev::WebThreeDirect (and dev::eth::Client) + * - KeyEventManager */ +#include +#include +#include #include +#include "libdevcrypto/FileSystem.h" +#include "KeyEventManager.h" #include "ApplicationCtx.h" +using namespace dev; using namespace dev::mix; +using namespace dev::eth; ApplicationCtx* ApplicationCtx::Instance = nullptr; +ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) +{ + m_applicationEngine = _engine; + m_keyEventManager = std::unique_ptr(); + m_webThree = std::unique_ptr(); + m_webThree.reset(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); + m_keyEventManager.reset(new KeyEventManager()); +} + +ApplicationCtx::~ApplicationCtx() +{ + delete m_applicationEngine; +} + QQmlApplicationEngine* ApplicationCtx::appEngine() { return m_applicationEngine; } +dev::eth::Client* ApplicationCtx::getEthereumClient() +{ + return m_webThree.get()->ethereum(); +} + +void ApplicationCtx::initKeyEventManager() +{ + QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); + if (mainContent) + { + QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); + } + else + qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!"; +} + +KeyEventManager* ApplicationCtx::getKeyEventManager() +{ + return m_keyEventManager.get(); +} + void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) { if (Instance == nullptr) Instance = new ApplicationCtx(_engine); } + +void ApplicationCtx::displayMessageDialog(QString _title, QString _message) +{ + QQmlComponent component(m_applicationEngine, QUrl("qrc:/qml/BasicMessage.qml")); + QObject* dialog = component.create(); + dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); + QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QMetaObject::invokeMethod(dialogWin, "close"); + dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWin->setProperty("title", _title); + dialogWin->setProperty("width", "250"); + dialogWin->setProperty("height", "100"); + QMetaObject::invokeMethod(dialogWin, "open"); +} diff --git a/mix/ApplicationCtx.h b/mix/ApplicationCtx.h index 37166ea05..05e4f3bb3 100644 --- a/mix/ApplicationCtx.h +++ b/mix/ApplicationCtx.h @@ -16,14 +16,19 @@ */ /** @file ApplicationCtx.h * @author Yann yann@ethdev.com - * @date 2014 - * Provide an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. + * For now ApplicationCtx provides reference to: + * - QQmlApplicationEngine + * - dev::WebThreeDirect (and dev::eth::Client) + * - KeyEventManager */ #pragma once #include +#include "libwebthree/WebThree.h" +#include "KeyEventManager.h" namespace dev { @@ -36,15 +41,21 @@ class ApplicationCtx: public QObject Q_OBJECT public: - ApplicationCtx(QQmlApplicationEngine* _engine) { m_applicationEngine = _engine; } - ~ApplicationCtx() { delete m_applicationEngine; } + ApplicationCtx(QQmlApplicationEngine* _engine); + ~ApplicationCtx(); static ApplicationCtx* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); + dev::eth::Client* getEthereumClient(); + void initKeyEventManager(); + KeyEventManager* getKeyEventManager(); + void displayMessageDialog(QString _title, QString _message); private: static ApplicationCtx* Instance; QQmlApplicationEngine* m_applicationEngine; + std::unique_ptr m_webThree; + std::unique_ptr m_keyEventManager; public slots: void quitApplication() { delete Instance; } diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp new file mode 100644 index 000000000..e8b0391d8 --- /dev/null +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -0,0 +1,84 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerCtrl.h + * @author Yann yann@ethdev.com + * @date 2014 + * display opcode debugging. + */ + +#include +#include +#include +#include "libethereum/Transaction.h" +#include "AssemblyDebuggerModel.h" +#include "AssemblyDebuggerCtrl.h" +#include "TransactionBuilder.h" +#include "KeyEventManager.h" +#include "ApplicationCtx.h" +#include "DebuggingStateWrapper.h" +using namespace dev::mix; + +AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) +{ + m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); + m_doc = _doc; +} + +QString AssemblyDebuggerCtrl::contentUrl() const +{ + return QStringLiteral("qrc:/qml/Debugger.qml"); +} + +QString AssemblyDebuggerCtrl::title() const +{ + return "debugger"; +} + +void AssemblyDebuggerCtrl::start() const +{ + //start to listen on F5 + ApplicationCtx::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); +} + +void AssemblyDebuggerCtrl::keyPressed(int _key) +{ + if (_key == Qt::Key_F5) + { + if (!m_modelDebugger->compile(m_doc->toPlainText())) + { + ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); + return; + } + + KeyPair ad = KeyPair::create(); + u256 gasPrice = 10000000000000; + u256 gas = 1000000; + u256 amount = 100; + DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText(), ad); + + //we need to wrap states in a QObject before sending to QML. + QList wStates; + for(int i = 0; i < debuggingContent.states.size(); i++) + { + DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes()); + s->setState(debuggingContent.states.at(i)); + wStates.append(s); + } + std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); + ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); + this->addContentOn(this); + }; +} diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h new file mode 100644 index 000000000..a1642cc14 --- /dev/null +++ b/mix/AssemblyDebuggerCtrl.h @@ -0,0 +1,55 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerCtrl.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "QTextDocument" +#include "Extension.h" +#include "ConstantCompilationModel.h" +#include "AssemblyDebuggerModel.h" + +namespace dev +{ + +namespace mix +{ + +class AssemblyDebuggerCtrl: public Extension +{ + Q_OBJECT + +public: + AssemblyDebuggerCtrl(QTextDocument*); + ~AssemblyDebuggerCtrl() {} + void start() const override; + QString title() const override; + QString contentUrl() const override; + +private: + std::unique_ptr m_modelDebugger; + QTextDocument* m_doc; + +public Q_SLOTS: + void keyPressed(int); +}; + +} + +} diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp new file mode 100644 index 000000000..c65beac7d --- /dev/null +++ b/mix/AssemblyDebuggerModel.cpp @@ -0,0 +1,111 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerModel.h + * @author Yann yann@ethdev.com + * @date 2014 + * used as a model to debug contract assembly code. + */ + +#include "libethereum/Executive.h" +#include "libethereum/Transaction.h" +#include "libethereum/ExtVM.h" +#include "libevm/VM.h" +#include "libdevcore/Common.h" +#include "ApplicationCtx.h" +#include "TransactionBuilder.h" +#include "AssemblyDebuggerModel.h" +#include "ConstantCompilationModel.h" +#include "DebuggingStateWrapper.h" +using namespace dev; +using namespace dev::eth; +using namespace dev::mix; + +AssemblyDebuggerModel::AssemblyDebuggerModel() +{ + m_currentExecution = std::unique_ptr(new Executive(m_executiveState)); +} + +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) +{ + QList states; + Transaction tr(_rawTransaction); + m_currentExecution.get()->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + std::vector levels; + bytes code; + bytesConstRef data; + bool firstIteration = true; + auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, void* voidVM, void const* voidExt) + { + VM& vm = *(VM*)voidVM; + ExtVM const& ext = *(ExtVM const*)voidExt; + + if (firstIteration) + { + code = ext.code; + data = ext.data; + firstIteration = false; + } + + if (levels.size() < ext.depth) + levels.push_back(&states.back()); + else + levels.resize(ext.depth); + + states.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), + vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); + }; + + m_currentExecution.get()->go(onOp); + m_currentExecution.get()->finalize(onOp); + + DebuggingContent d; + d.states = states; + d.executionCode = code; + d.executionData = data; + d.contentAvailable = true; + d.message = "ok"; + return d; +} + + +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, + dev::u256 _gasPrice, + dev::u256 _gas, + QString code, + KeyPair _key) +{ + ConstantCompilationModel compiler; + CompilerResult res = compiler.compile(code); + if (!res.success) + { + DebuggingContent r; + r.contentAvailable = false; + r.message = "compile failed"; + return r; + } + + TransactionBuilder trBuild; + Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, _gas, res.bytes, + m_executiveState.transactionsFrom(dev::toAddress(_key.secret())), _key.secret()); + bytes b = tr.rlp(); + dev::bytesConstRef bytesRef = &b; + return getContractInitiationDebugStates(bytesRef); +} + +bool AssemblyDebuggerModel::compile(QString code) +{ + ConstantCompilationModel compiler; + CompilerResult res = compiler.compile(code); + return res.success; +} diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h new file mode 100644 index 000000000..3cac98db0 --- /dev/null +++ b/mix/AssemblyDebuggerModel.h @@ -0,0 +1,49 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file AssemblyDebuggerModel.h + * @author Yann yann@ethdev.com + * @date 2014 + * serves as a model to debug contract assembly code. + */ + +#pragma once + +#include +#include +#include "libethereum/State.h" +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" +#include "DebuggingStateWrapper.h" +namespace dev +{ + +namespace mix +{ + +class AssemblyDebuggerModel +{ +public: + AssemblyDebuggerModel(); + DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); + DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); + bool compile(QString code); + +private: + std::unique_ptr m_currentExecution; + dev::eth::State m_executiveState; +}; + +} + +} diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 596aea165..c85292f2b 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -27,6 +27,7 @@ #include #include #include "ConstantCompilationCtrl.h" +#include "AssemblyDebuggerCtrl.h" #include "features.h" #include "ApplicationCtx.h" #include "CodeEditorExtensionManager.h" @@ -59,22 +60,29 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor) void CodeEditorExtensionManager::initExtensions() { - //only one for now - std::shared_ptr constantCompilation = std::make_shared(m_doc); - if (constantCompilation.get()->contentUrl() != "") + initExtension(std::make_shared(m_doc)); + initExtension(std::make_shared(m_doc)); +} + +void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) +{ + if (!ext.get()->contentUrl().isEmpty()) { try { - constantCompilation.get()->addContentOn(m_tabView); + if (ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + { + ext.get()->addTabOn(m_tabView); + } } catch (...) { - qDebug() << "Exception when adding content into view."; + qDebug() << "Exception when adding tab into view."; return; } } - constantCompilation.get()->start(); - m_features.append(constantCompilation); + ext.get()->start(); + m_features.append(ext); } void CodeEditorExtensionManager::setEditor(QQuickItem* _editor) diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 2b8402bf2..8e8501bc9 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -45,12 +45,13 @@ public: CodeEditorExtensionManager() {} ~CodeEditorExtensionManager(); void initExtensions(); + void initExtension(std::shared_ptr); void setEditor(QQuickItem*); void setTabView(QQuickItem*); private: QQuickItem* m_editor; - QVector> m_features; + QVector> m_features; QQuickItem* m_tabView; QTextDocument* m_doc; void loadEditor(QQuickItem*); diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 06b9c0284..a703e6686 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -30,7 +30,7 @@ #include "ConstantCompilationModel.h" using namespace dev::mix; -ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc) +ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) { m_editor = _doc; m_compilationModel = new ConstantCompilationModel(); @@ -64,7 +64,7 @@ void ConstantCompilationCtrl::compile() resetOutPut(); return; } - CompilerResult res = m_compilationModel->compile(m_editor->toPlainText()); + CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); writeOutPut(res); } diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index e06734f59..a6b2f2741 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -42,6 +42,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) res.success = true; res.comment = "ok"; res.hexCode = QString::fromStdString(dev::eth::disassemble(m_data)); + res.bytes = m_data; } catch (dev::Exception const& _exception) { diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 4a17853f6..01ad32224 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -22,6 +22,7 @@ #pragma once +#include #include namespace dev @@ -34,6 +35,7 @@ struct CompilerResult { QString hexCode; QString comment; + dev::bytes bytes; bool success; }; diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp new file mode 100644 index 000000000..877598ca5 --- /dev/null +++ b/mix/DebuggingStateWrapper.cpp @@ -0,0 +1,189 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DebuggingState.h + * @author Yann yann@ethdev.com + * @date 2014 + * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). + */ + +#include +#include +#include +#include "libdevcrypto/Common.h" +#include "libevmcore/Instruction.h" +#include "libdevcore/Common.h" +#include "DebuggingStateWrapper.h" +using namespace dev; +using namespace dev::eth; +using namespace dev::mix; + +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code) +{ + QList codeStr; + QMap codeMapping; + for (unsigned i = 0; i <= code.size(); ++i) + { + byte b = i < code.size() ? code[i] : 0; + try + { + QString s = QString::fromStdString(instructionInfo((Instruction)b).name); + std::ostringstream out; + out << hex << std::setw(4) << std::setfill('0') << i; + codeMapping[i] = codeStr.size(); + int line = i; + if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) + { + unsigned bc = b - (byte)Instruction::PUSH1 + 1; + s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); + i += bc; + } + HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line); + codeStr.append(humanCode); + } + catch (...) + { + qDebug() << QString("Unhandled exception!") << endl << + QString::fromStdString(boost::current_exception_diagnostic_information()); + break; // probably hit data segment + } + } + return std::make_tuple(codeStr, new QQMLMap(codeMapping)); +} + +QString DebuggingStateWrapper::debugStack() +{ + QString stack; + for (auto i: m_state.stack) + stack.prepend(prettyU256(i) + "\n"); + + return stack; +} + +QString DebuggingStateWrapper::debugStorage() +{ + std::stringstream s; + for (auto const& i: m_state.storage) + s << "@" << prettyU256(i.first).toStdString() << "    " << prettyU256(i.second).toStdString(); + + return QString::fromStdString(s.str()); +} + +QString DebuggingStateWrapper::debugMemory() +{ + return QString::fromStdString(memDump(m_state.memory, 16, false)); +} + +QString DebuggingStateWrapper::debugCallData() +{ + + return QString::fromStdString(memDump(m_data, 16, false)); +} + +QStringList DebuggingStateWrapper::levels() +{ + QStringList levelsStr; + for (unsigned i = 0; i <= m_state.levels.size(); ++i) + { + DebuggingState const& s = i ? *m_state.levels[m_state.levels.size() - i] : m_state; + std::ostringstream out; + out << m_state.cur.abridged(); + if (i) + out << " " << instructionInfo(m_state.inst).name << " @0x" << hex << m_state.curPC; + levelsStr.append(QString::fromStdString(out.str())); + } + return levelsStr; +} + +QString DebuggingStateWrapper::headerInfo() +{ + std::ostringstream ss; + ss << dec << " STEP: " << m_state.steps << " | PC: 0x" << hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << dec << m_state.newMemSize << " words | COST: " << dec << m_state.gasCost << " | GAS: " << dec << m_state.gas; + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::endOfDebug() +{ + if (m_state.gasCost > m_state.gas) + return "OUT-OF-GAS"; + else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) + { + unsigned from = (unsigned)m_state.stack.back(); + unsigned size = (unsigned)m_state.stack[m_state.stack.size() - 2]; + unsigned o = 0; + bytes out(size, 0); + for (; o < size && from + o < m_state.memory.size(); ++o) + out[o] = m_state.memory[from + o]; + return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); + } + else if (m_state.inst == Instruction::STOP) + return "STOP"; + else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) + return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + else + return "EXCEPTION"; +} + +QString DebuggingStateWrapper::prettyU256(u256 _n) +{ + unsigned inc = 0; + QString raw; + std::ostringstream s; + if (!(_n >> 64)) + s << " " << (uint64_t)_n << " (0x" << hex << (uint64_t)_n << ")"; + else if (!~(_n >> 64)) + s << " " << (int64_t)_n << " (0x" << hex << (int64_t)_n << ")"; + else if ((_n >> 160) == 0) + { + Address a = right160(_n); + + QString n = QString::fromStdString(a.abridged());//pretty(a); + if (n.isNull()) + s << "0x" << a; + else + s << n.toHtmlEscaped().toStdString() << "(0x" << a.abridged() << ")"; + } + else if ((raw = fromRaw((h256)_n, &inc)).size()) + return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : ""); + else + s << "" << (h256)_n; + return QString::fromStdString(s.str()); +} + +QString DebuggingStateWrapper::fromRaw(h256 _n, unsigned* _inc) +{ + if (_n) + { + std::string s((char const*)_n.data(), 32); + auto l = s.find_first_of('\0'); + if (!l) + return QString(); + if (l != std::string::npos) + { + auto p = s.find_first_not_of('\0', l); + if (!(p == std::string::npos || (_inc && p == 31))) + return QString(); + if (_inc) + *_inc = (byte)s[31]; + s.resize(l); + } + for (auto i: s) + if (i < 32) + return QString(); + return QString::fromStdString(s); + } + return QString(); +} diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h new file mode 100644 index 000000000..07716e9ad --- /dev/null +++ b/mix/DebuggingStateWrapper.h @@ -0,0 +1,133 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DebuggingState.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "libethereum/State.h" +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" + +namespace dev +{ + +namespace mix +{ + +struct DebuggingState +{ + uint64_t steps; + dev::Address cur; + dev::u256 curPC; + dev::eth::Instruction inst; + dev::bigint newMemSize; + dev::u256 gas; + dev::u256s stack; + dev::bytes memory; + dev::bigint gasCost; + std::map storage; + std::vector levels; +}; + +struct DebuggingContent +{ + QList states; + bytes executionCode; + bytesConstRef executionData; + bool contentAvailable; + QString message; +}; + +/* contains the line nb of the assembly code and the corresponding index in the code bytes array */ +class HumanReadableCode: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString line READ line) + Q_PROPERTY(int processIndex READ processIndex) + +public: + HumanReadableCode(QString _line, int _processIndex) : m_line(_line), m_processIndex(_processIndex) {} + QString line() { return m_line; } + int processIndex() { return m_processIndex; } + +private: + QString m_line; + int m_processIndex; +}; + +/* used to publish QMap type to QML */ +class QQMLMap : public QObject +{ + Q_OBJECT + +public: + QQMLMap(QMap _map) : m_map(_map) { } + Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + +private: + QMap m_map; +}; + +/* used to publish DebuggingState struct to QML */ +class DebuggingStateWrapper : public QObject +{ + Q_OBJECT + Q_PROPERTY(int step READ step) + Q_PROPERTY(int curPC READ curPC) + Q_PROPERTY(int gasCost READ gasCost) + Q_PROPERTY(int gas READ gas) + Q_PROPERTY(QString debugStack READ debugStack) + Q_PROPERTY(QString debugStorage READ debugStorage) + Q_PROPERTY(QString debugMemory READ debugMemory) + Q_PROPERTY(QString debugCallData READ debugCallData) + Q_PROPERTY(QString headerInfo READ headerInfo) + Q_PROPERTY(QString endOfDebug READ endOfDebug) + Q_PROPERTY(QStringList levels READ levels) + +public: + DebuggingStateWrapper(bytes _code, bytes _data) : m_code(_code), m_data(_data) {} + int step() { return (int)m_state.steps; } + int curPC() { return (int)m_state.curPC; } + int gasCost() { return (int)m_state.gasCost; } + int gas() { return (int)m_state.gas; } + QString debugStack(); + QString debugStorage(); + QString debugMemory(); + QString debugCallData(); + QString headerInfo(); + QString endOfDebug(); + QStringList levels(); + DebuggingState state() { return m_state; } + void setState(DebuggingState _state) { m_state = _state; } + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code); + +private: + DebuggingState m_state; + bytes m_code; + bytes m_data; + QString prettyU256(u256 _n); + QString fromRaw(h256 _n, unsigned* _inc = nullptr); +}; + +} + +} diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 5aeb0cc17..24cc19aba 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -25,7 +25,7 @@ using namespace dev; using namespace dev::mix; -void Extension::addContentOn(QObject* _tabView) +void Extension::addTabOn(QObject* _view) { if (contentUrl() == "") return; @@ -33,12 +33,29 @@ void Extension::addContentOn(QObject* _tabView) QVariant returnValue; QQmlComponent* component = new QQmlComponent( ApplicationCtx::getInstance()->appEngine(), - QUrl(this->contentUrl()), _tabView); + QUrl(contentUrl()), _view); - QMetaObject::invokeMethod(_tabView, "addTab", - Q_RETURN_ARG(QVariant, returnValue), - Q_ARG(QVariant, this->title()), - Q_ARG(QVariant, QVariant::fromValue(component))); + QMetaObject::invokeMethod(_view, "addTab", + Q_RETURN_ARG(QVariant, returnValue), + Q_ARG(QVariant, this->title()), + Q_ARG(QVariant, QVariant::fromValue(component))); m_view = qvariant_cast(returnValue); } + +void Extension::addContentOn(QObject* _view) +{ + Q_UNUSED(_view); + if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) + { + QQmlComponent component(ApplicationCtx::getInstance()->appEngine(), QUrl(contentUrl())); + QObject* dialog = component.create(); + QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QMetaObject::invokeMethod(dialogWin, "close"); + dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWin->setProperty("title", title()); + QMetaObject::invokeMethod(dialogWin, "open"); + } + //TODO add more view type. +} + diff --git a/mix/Extension.h b/mix/Extension.h index f8fef0aa6..b697af58b 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -28,19 +28,31 @@ namespace dev namespace mix { +enum ExtensionDisplayBehavior +{ + Tab, + ModalDialog +}; + + class Extension: public QObject { Q_OBJECT public: Extension() {} + Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } virtual QString contentUrl() const { return ""; } virtual QString title() const { return ""; } virtual void start() const {} - void addContentOn(QObject* tabView); + void addContentOn(QObject* _tabView); + void addTabOn(QObject* _view); + void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } + ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; } protected: QObject* m_view; + ExtensionDisplayBehavior m_displayBehavior; }; } diff --git a/mix/KeyEventManager.cpp b/mix/KeyEventManager.cpp new file mode 100644 index 000000000..f5d638869 --- /dev/null +++ b/mix/KeyEventManager.cpp @@ -0,0 +1,43 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file KeyEventManager.cpp + * @author Yann yann@ethdev.com + * @date 2014 + * Used as an event handler for all classes which need keyboard interactions. + * Can be improve by adding the possibility to register to a specific key. + */ + +#include +#include +#include "KeyEventManager.h" + +void KeyEventManager::registerEvent(const QObject* _receiver, const char* _slot) +{ + QObject::connect(this, SIGNAL(onKeyPressed(int)), _receiver, _slot); +} + +void KeyEventManager::unRegisterEvent(QObject* _receiver) +{ + QObject::disconnect(_receiver); +} + +void KeyEventManager::keyPressed(QVariant _event) +{ + emit onKeyPressed(_event.toInt()); +} + + diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h new file mode 100644 index 000000000..ecd768c4c --- /dev/null +++ b/mix/KeyEventManager.h @@ -0,0 +1,42 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file KeyEventManager.h + * @author Yann yann@ethdev.com + * @date 2014 + * use as an event handler for all classes which need keyboard interactions + */ + +#pragma once + +#include + +class KeyEventManager: public QObject +{ + Q_OBJECT + +public: + KeyEventManager() {} + void registerEvent(const QObject* receiver, const char* slot); + void unRegisterEvent(QObject* receiver); + +signals: + void onKeyPressed(int); + +public Q_SLOTS: + void keyPressed(QVariant event); +}; + diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp new file mode 100644 index 000000000..ce274fa00 --- /dev/null +++ b/mix/TransactionBuilder.cpp @@ -0,0 +1,92 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file TransactionBuilder.cpp + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#include "libethereum/Executive.h" +#include "libdevcore/Common.h" +#include "ApplicationCtx.h" +#include "TransactionBuilder.h" +using namespace dev::mix; +using namespace dev::eth; +using namespace dev; + +Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPrice, u256 _gas, + bytes _data, u256 _nonce, Secret _secret) const +{ + return Transaction(_value, _gasPrice, _gas, _data, _nonce, _secret); +} + +Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, + QString address, bytes _data, u256 _nonce, Secret _secret) const +{ + return Transaction(_value, _gasPrice, _gas, fromString(address), _data, _nonce, _secret); +} + +int TransactionBuilder::fromHex(char _i) const +{ + if (_i >= '0' && _i <= '9') + return _i - '0'; + if (_i >= 'a' && _i <= 'f') + return _i - 'a' + 10; + if (_i >= 'A' && _i <= 'F') + return _i - 'A' + 10; + BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i)); +} + +bytes TransactionBuilder::fromHex(std::string const& _s) const +{ + unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0; + std::vector ret; + ret.reserve((_s.size() - s + 1) / 2); + + if (_s.size() % 2) + try + { + ret.push_back(fromHex(_s[s++])); + } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + for (unsigned i = s; i < _s.size(); i += 2) + try + { + ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); + } + catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } + return ret; +} + +Address TransactionBuilder::fromString(QString const& _a) const +{ + Client* ethClient = ApplicationCtx::getInstance()->getEthereumClient(); + std::string sn = _a.toStdString(); + if (sn.size() > 32) + sn.resize(32); + h256 n; + memcpy(n.data(), sn.data(), sn.size()); + memset(n.data() + sn.size(), 0, 32 - sn.size()); + if (_a.size() == 40) + return Address(fromHex(_a.toStdString())); + else + { + //we try to resolve the recipient adress using nameReg contract state + const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract + if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) + if (h256 a = ethClient->stateAt(nameReg, n)) + return right160(a); + } + return Address(); // should maybe throws exception instead of returning blank address. +} diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h new file mode 100644 index 000000000..261d3060f --- /dev/null +++ b/mix/TransactionBuilder.h @@ -0,0 +1,48 @@ +/* + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file TransactionBuilder.h + * @author Yann yann@ethdev.com + * @date 2014 + * Ethereum IDE client. + */ + +#pragma once + +#include +#include "libdevcore/Common.h" +#include "libethereum/Transaction.h" + +namespace dev +{ + +namespace mix +{ + +class TransactionBuilder +{ +public: + TransactionBuilder() {} + dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; + dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + dev::bytes _data, dev::u256 _nonce, Secret _secret) const; +private: + bytes fromHex(std::string const& _s) const; + int fromHex(char _i) const; + Address fromString(QString const& _a) const; +}; + +} + +} diff --git a/mix/main.cpp b/mix/main.cpp index 537941290..4f707f47a 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,6 +35,9 @@ int main(int _argc, char *_argv[]) QQmlApplicationEngine* engine = new QQmlApplicationEngine(); ApplicationCtx::setApplicationContext(engine); QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff + engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); + + ApplicationCtx::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. return app.exec(); } diff --git a/mix/qml.qrc b/mix/qml.qrc index 267427ce5..2fa92d661 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -4,5 +4,8 @@ qml/main.qml qml/MainContent.qml qml/TabStyle.qml + qml/Debugger.qml + qml/js/Debugger.js + qml/BasicMessage.qml diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml new file mode 100644 index 000000000..14ddbcf0d --- /dev/null +++ b/mix/qml/BasicMessage.qml @@ -0,0 +1,20 @@ +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 + +Rectangle { + anchors.fill: parent + color: "lightgrey" + Label + { + width: parent.width + height: parent.height + horizontalAlignment: "AlignHCenter" + verticalAlignment: "AlignVCenter" + objectName: "messageContent" + id: messageTxt + text: "" + } +} diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml new file mode 100644 index 000000000..1c79e43ce --- /dev/null +++ b/mix/qml/Debugger.qml @@ -0,0 +1,231 @@ +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import "js/Debugger.js" as Debugger + +Rectangle { + anchors.fill: parent; + Rectangle { + id: headerInfo + width: parent.width + height: 30 + anchors.top: parent.top + Label { + anchors.centerIn: parent + font.family: "Verdana" + font.pointSize: 9 + font.italic: true + id: headerInfoLabel + } + + } + + Keys.onPressed: { + if (event.key === Qt.Key_F10) + Debugger.moveSelection(1); + else if (event.key === Qt.Key_F9) + Debugger.moveSelection(-1); + } + + Rectangle { + id: stateListContainer + focus: true + anchors.top: headerInfo.bottom + anchors.left: parent.left + height: parent.height - 30 + width: parent.width * 0.5 + + ListView { + anchors.top: parent.top + height: parent.height * 0.55 + width: 200 + anchors.horizontalCenter: parent.horizontalCenter + id: statesList + Component.onCompleted: Debugger.init(); + model: humanReadableExecutionCode + delegate: renderDelegate + highlight: highlightBar + highlightFollowsCurrentItem: true + } + + Component { + id: highlightBar + Rectangle { + height: statesList.currentItem.height + width: statesList.currentItem.width + border.color: "orange" + border.width: 1 + Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } + } + } + + Component { + id: renderDelegate + Item { + id: wrapperItem + height:20 + width: parent.width + Text { + anchors.centerIn: parent + text: line + font.pointSize: 9 + } + } + } + + Rectangle { + anchors.top: statesList.bottom + height: parent.height * 0.30 + width: parent.width + + Label { + id: callStackLabel + anchors.top: statesList.bottom + anchors.bottomMargin: 10 + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + text: "callstack" + } + + ListView { + height: parent.height - 15 + width: 200 + anchors.top: callStackLabel.bottom + anchors.horizontalCenter: parent.horizontalCenter + id: levelList + delegate: Component { + Item { + Text { + font.family: "Verdana" + font.pointSize: 8 + text: modelData + } + } + } + } + } + } + + Rectangle { + anchors.topMargin: 5 + anchors.bottomMargin: 10 + anchors.rightMargin: 10 + height: parent.height - 30 + width: parent.width * 0.5 + anchors.right: parent.right + anchors.top: headerInfo.bottom + anchors.bottom: parent.bottom + + Rectangle { + id: debugStack + anchors.top: parent.top + width: parent.width + height: parent.height * 0.25 + + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug stack" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id:debugStackTxt + readOnly: true; + } + } + + Rectangle { + id: debugMemory + anchors.top: debugStack.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug memory" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id: debugMemoryTxt + readOnly: true; + } + } + + Rectangle { + id: debugStorage + anchors.top: debugMemory.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug storage" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + height: parent.height - 15 + id:debugStorageTxt + readOnly: true; + } + } + + Rectangle { + id: debugCallData + anchors.top: debugStorage.bottom + width: parent.width + height: parent.height * 0.25 + Label { + horizontalAlignment: "AlignHCenter" + font.family: "Verdana" + font.pointSize: 8 + font.letterSpacing: 2 + width: parent.width + height: 15 + anchors.top : parent.top + text: "debug calldata" + } + TextArea { + anchors.bottom: parent.bottom + width: parent.width + height: parent.height - 15 + id: debugCallDataTxt + readOnly: true; + } + } + } +} diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index bd4737c3b..821b48913 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,10 +1,18 @@ -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.3 +import QtQuick.Controls 1.2 import QtQuick.Layouts 1.0 -import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls.Styles 1.2 import CodeEditorExtensionManager 1.0 Rectangle { + objectName: "mainContent" + signal keyPressed(variant event) + focus: true + Keys.enabled: true + Keys.onPressed: + { + root.keyPressed(event.key); + } anchors.fill: parent height: parent.height width: parent.width; @@ -26,11 +34,11 @@ Rectangle { anchors.centerIn: parent tabChangesFocus: false Keys.onPressed: { - if (event.key === Qt.Key_Tab) { - codeEditor.insert(codeEditor.cursorPosition, "\t"); - event.accepted = true; + if (event.key === Qt.Key_Tab) { + codeEditor.insert(codeEditor.cursorPosition, "\t"); + event.accepted = true; + } } - } } } Rectangle { @@ -46,7 +54,7 @@ Rectangle { style: TabStyle {} } } - CodeEditorExtensionManager{ + CodeEditorExtensionManager { tabView: contextualTabs editor: codeEditor } diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js new file mode 100644 index 000000000..ddaa362a6 --- /dev/null +++ b/mix/qml/js/Debugger.js @@ -0,0 +1,63 @@ +//humanReadableExecutionCode => contain human readable code. +//debugStates => contain all debug states. +//bytesCodeMapping => mapping between humanReadableExecutionCode and bytesCode. +//statesList => ListView + +var currentSelectedState = null; +function init() +{ + currentSelectedState = 0; + select(currentSelectedState); +} + +function moveSelection(incr) +{ + if (currentSelectedState + incr >= 0) + { + if (currentSelectedState + incr < debugStates.length) + { + select(currentSelectedState + incr); + } + else + { + endOfDebug(); + } + } +} + +function select(stateIndex) +{ + var state = debugStates[stateIndex]; + var codeStr = bytesCodeMapping.getValue(state.curPC); + highlightSelection(codeStr); + currentSelectedState = codeStr; + completeCtxInformation(state); + levelList.model = state.levels; + levelList.update(); +} + +function highlightSelection(index) +{ + console.log(index); + statesList.currentIndex = index; +} + +function completeCtxInformation(state) +{ + debugStackTxt.text = state.debugStack; + debugStorageTxt.text = state.debugStorage; + debugMemoryTxt.text = state.debugMemory; + debugCallDataTxt.text = state.debugCallData; + headerInfoLabel.text = state.headerInfo +} + +function endOfDebug() +{ + var state = debugStates[debugStates.length - 1]; + debugStorageTxt.text = ""; + debugCallDataTxt.text = ""; + debugStackTxt.text = ""; + debugMemoryTxt.text = state.endOfDebug + var gascost = state.gas - state.gasCost; + headerInfoLabel.text = "EXIT | GAS: " + gascost; +} diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 3553f7710..05b29eb62 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -1,15 +1,22 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.0 import CodeEditorExtensionManager 1.0 ApplicationWindow { + id: mainApplication visible: true - width: 1000 - height: 480 + x: Screen.width / 2 - width / 2 + y: Screen.height / 2 - height / 2 + width: 1200 + height: 600 minimumWidth: 400 minimumHeight: 300 title: qsTr("mix") + menuBar: MenuBar { Menu { title: qsTr("File") @@ -19,6 +26,33 @@ ApplicationWindow { } } } - MainContent{ + + MainContent { + } + + Dialog { + x: mainApplication.x + (mainApplication.width - width) / 2 + y: mainApplication.y + (mainApplication.height - height) / 2 + objectName: "dialog" + id: dialog + height: 400 + width: 700 + modality: Qt.WindowModal + contentItem: Rectangle { + objectName: "dialogContent" + } + } + + Dialog { + x: mainApplication.x + (mainApplication.width - width) / 2 + y: mainApplication.y + (mainApplication.height - height) / 2 + objectName: "messageDialog" + id: messageDialog + height: 150 + width: 200 + modality: Qt.WindowModal + contentItem: Rectangle { + objectName: "messageContent" + } } } From 803b47161ec05acea00129d4afa6dd93c6c943f0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 11:27:09 +0100 Subject: [PATCH 02/20] debug modal dialog UI correction --- mix/qml/Debugger.qml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 1c79e43ce..490f49f61 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -7,7 +7,9 @@ import "js/Debugger.js" as Debugger Rectangle { anchors.fill: parent; + color: "lightgrey" Rectangle { + color: "transparent" id: headerInfo width: parent.width height: 30 @@ -30,8 +32,10 @@ Rectangle { } Rectangle { + color: "transparent" id: stateListContainer focus: true + anchors.topMargin: 10 anchors.top: headerInfo.bottom anchors.left: parent.left height: parent.height - 30 @@ -39,7 +43,7 @@ Rectangle { ListView { anchors.top: parent.top - height: parent.height * 0.55 + height: parent.height * 0.60 width: 200 anchors.horizontalCenter: parent.horizontalCenter id: statesList @@ -65,7 +69,7 @@ Rectangle { id: renderDelegate Item { id: wrapperItem - height:20 + height: 20 width: parent.width Text { anchors.centerIn: parent @@ -76,13 +80,14 @@ Rectangle { } Rectangle { + id: callStackPanel anchors.top: statesList.bottom - height: parent.height * 0.30 + height: parent.height * 0.35 width: parent.width - + anchors.topMargin: 13 + color: "transparent" Label { id: callStackLabel - anchors.top: statesList.bottom anchors.bottomMargin: 10 horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -113,6 +118,7 @@ Rectangle { } Rectangle { + color: "transparent" anchors.topMargin: 5 anchors.bottomMargin: 10 anchors.rightMargin: 10 @@ -127,7 +133,7 @@ Rectangle { anchors.top: parent.top width: parent.width height: parent.height * 0.25 - + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -155,6 +161,7 @@ Rectangle { anchors.top: debugStack.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -182,6 +189,7 @@ Rectangle { anchors.top: debugMemory.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" @@ -209,6 +217,7 @@ Rectangle { anchors.top: debugStorage.bottom width: parent.width height: parent.height * 0.25 + color: "transparent" Label { horizontalAlignment: "AlignHCenter" font.family: "Verdana" From dbc5201e98c1fdc1e09f1fe3108a6c10f6b20fc1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 12:57:09 +0100 Subject: [PATCH 03/20] - coding standards. - set 'parent' on QObject custom class to ensure object deletion. --- mix/ApplicationCtx.cpp | 6 ++---- mix/AssemblyDebuggerCtrl.cpp | 2 +- mix/AssemblyDebuggerModel.cpp | 1 - mix/AssemblyDebuggerModel.h | 1 + mix/CodeEditorExtensionManager.cpp | 12 ++++++------ mix/ConstantCompilationModel.h | 2 +- mix/DebuggingStateWrapper.cpp | 6 +++--- mix/DebuggingStateWrapper.h | 6 +++--- mix/qml/Debugger.qml | 2 +- 9 files changed, 18 insertions(+), 20 deletions(-) diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index 52e66dab7..99d9bee4c 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -38,10 +38,8 @@ ApplicationCtx* ApplicationCtx::Instance = nullptr; ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) { m_applicationEngine = _engine; - m_keyEventManager = std::unique_ptr(); - m_webThree = std::unique_ptr(); - m_webThree.reset(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); - m_keyEventManager.reset(new KeyEventManager()); + m_keyEventManager = std::unique_ptr(new KeyEventManager()); + m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } ApplicationCtx::~ApplicationCtx() diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index e8b0391d8..94d8bf6cb 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -75,7 +75,7 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) s->setState(debuggingContent.states.at(i)); wStates.append(s); } - std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode); + std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index c65beac7d..df027acf7 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -78,7 +78,6 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by return d; } - DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 3cac98db0..378f238e6 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -25,6 +25,7 @@ #include "libethereum/Executive.h" #include "libdevcore/Common.h" #include "DebuggingStateWrapper.h" + namespace dev { diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index c85292f2b..503e07447 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -64,15 +64,15 @@ void CodeEditorExtensionManager::initExtensions() initExtension(std::make_shared(m_doc)); } -void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) +void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) { - if (!ext.get()->contentUrl().isEmpty()) + if (!_ext.get()->contentUrl().isEmpty()) { try { - if (ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + if (_ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) { - ext.get()->addTabOn(m_tabView); + _ext.get()->addTabOn(m_tabView); } } catch (...) @@ -81,8 +81,8 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr ext) return; } } - ext.get()->start(); - m_features.append(ext); + _ext.get()->start(); + m_features.append(_ext); } void CodeEditorExtensionManager::setEditor(QQuickItem* _editor) diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 01ad32224..713c9e950 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -45,7 +45,7 @@ class ConstantCompilationModel public: ConstantCompilationModel() {} ~ConstantCompilationModel() {} - CompilerResult compile(QString code); + CompilerResult compile(QString); }; } diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 877598ca5..3bce8658b 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -31,7 +31,7 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code) +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code, QObject* _objUsedAsParent) { QList codeStr; QMap codeMapping; @@ -51,7 +51,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); i += bc; } - HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line); + HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); codeStr.append(humanCode); } catch (...) @@ -61,7 +61,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod break; // probably hit data segment } } - return std::make_tuple(codeStr, new QQMLMap(codeMapping)); + return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent)); } QString DebuggingStateWrapper::debugStack() diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 07716e9ad..0285a4693 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -65,7 +65,7 @@ class HumanReadableCode: public QObject Q_PROPERTY(int processIndex READ processIndex) public: - HumanReadableCode(QString _line, int _processIndex) : m_line(_line), m_processIndex(_processIndex) {} + HumanReadableCode(QString _line, int _processIndex, QObject* _parent) : m_line(_line), m_processIndex(_processIndex), QObject(_parent) {} QString line() { return m_line; } int processIndex() { return m_processIndex; } @@ -80,7 +80,7 @@ class QQMLMap : public QObject Q_OBJECT public: - QQMLMap(QMap _map) : m_map(_map) { } + QQMLMap(QMap _map, QObject* _parent) : m_map(_map), QObject(_parent) { } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: @@ -118,7 +118,7 @@ public: QStringList levels(); DebuggingState state() { return m_state; } void setState(DebuggingState _state) { m_state = _state; } - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code); + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code, QObject* _objUsedAsParent); private: DebuggingState m_state; diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 490f49f61..6802f57df 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -84,7 +84,7 @@ Rectangle { anchors.top: statesList.bottom height: parent.height * 0.35 width: parent.width - anchors.topMargin: 13 + anchors.topMargin: 15 color: "transparent" Label { id: callStackLabel From 827de531b9f2f6d68c7ebbb40ed201d1f46a713b Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 13:07:42 +0100 Subject: [PATCH 04/20] - Coding standards --- mix/AssemblyDebuggerModel.cpp | 4 ++-- mix/AssemblyDebuggerModel.h | 2 +- mix/CodeEditorExtensionManager.cpp | 1 - mix/DebuggingStateWrapper.cpp | 8 ++++---- mix/MixApplication.cpp | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index df027acf7..e4c2396ca 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -102,9 +102,9 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 return getContractInitiationDebugStates(bytesRef); } -bool AssemblyDebuggerModel::compile(QString code) +bool AssemblyDebuggerModel::compile(QString _code) { ConstantCompilationModel compiler; - CompilerResult res = compiler.compile(code); + CompilerResult res = compiler.compile(_code); return res.success; } diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 378f238e6..c0941dc8f 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -38,7 +38,7 @@ public: AssemblyDebuggerModel(); DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); - bool compile(QString code); + bool compile(QString); private: std::unique_ptr m_currentExecution; diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 503e07447..3bef1a828 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -28,7 +28,6 @@ #include #include "ConstantCompilationCtrl.h" #include "AssemblyDebuggerCtrl.h" -#include "features.h" #include "ApplicationCtx.h" #include "CodeEditorExtensionManager.h" using namespace dev::mix; diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 3bce8658b..d96c975cd 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -31,13 +31,13 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code, QObject* _objUsedAsParent) +std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code, QObject* _objUsedAsParent) { QList codeStr; QMap codeMapping; - for (unsigned i = 0; i <= code.size(); ++i) + for (unsigned i = 0; i <= _code.size(); ++i) { - byte b = i < code.size() ? code[i] : 0; + byte b = i < _code.size() ? _code[i] : 0; try { QString s = QString::fromStdString(instructionInfo((Instruction)b).name); @@ -48,7 +48,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) { unsigned bc = b - (byte)Instruction::PUSH1 + 1; - s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc))); + s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index e67ca1b12..86507329c 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -23,7 +23,7 @@ #include "MixApplication.h" using namespace dev::mix; -MixApplication::MixApplication(int _argc, char *_argv[]): QApplication(_argc, _argv) +MixApplication::MixApplication(int _argc, char* _argv[]): QApplication(_argc, _argv) { } From 85fa520d1b8b9487a28b176cd774d404ccee3b56 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 13:17:37 +0100 Subject: [PATCH 05/20] - Coding Standards --- mix/DebuggingStateWrapper.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 0285a4693..3f03004b8 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -65,7 +65,7 @@ class HumanReadableCode: public QObject Q_PROPERTY(int processIndex READ processIndex) public: - HumanReadableCode(QString _line, int _processIndex, QObject* _parent) : m_line(_line), m_processIndex(_processIndex), QObject(_parent) {} + HumanReadableCode(QString _line, int _processIndex, QObject* _parent): QObject(_parent), m_line(_line), m_processIndex(_processIndex) {} QString line() { return m_line; } int processIndex() { return m_processIndex; } @@ -75,12 +75,12 @@ private: }; /* used to publish QMap type to QML */ -class QQMLMap : public QObject +class QQMLMap: public QObject { Q_OBJECT public: - QQMLMap(QMap _map, QObject* _parent) : m_map(_map), QObject(_parent) { } + QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: @@ -88,7 +88,7 @@ private: }; /* used to publish DebuggingState struct to QML */ -class DebuggingStateWrapper : public QObject +class DebuggingStateWrapper: public QObject { Q_OBJECT Q_PROPERTY(int step READ step) From eb3e005dee2b03a2fa43b4d806338996a4586d97 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 5 Dec 2014 16:20:00 +0100 Subject: [PATCH 06/20] use unique_ptr for QQMLApplicationEngine --- mix/ApplicationCtx.cpp | 11 +++-------- mix/ApplicationCtx.h | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/mix/ApplicationCtx.cpp b/mix/ApplicationCtx.cpp index 99d9bee4c..0130f2dfb 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/ApplicationCtx.cpp @@ -37,19 +37,14 @@ ApplicationCtx* ApplicationCtx::Instance = nullptr; ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) { - m_applicationEngine = _engine; + m_applicationEngine = std::unique_ptr(_engine); m_keyEventManager = std::unique_ptr(new KeyEventManager()); m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } -ApplicationCtx::~ApplicationCtx() -{ - delete m_applicationEngine; -} - QQmlApplicationEngine* ApplicationCtx::appEngine() { - return m_applicationEngine; + return m_applicationEngine.get(); } dev::eth::Client* ApplicationCtx::getEthereumClient() @@ -81,7 +76,7 @@ void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) void ApplicationCtx::displayMessageDialog(QString _title, QString _message) { - QQmlComponent component(m_applicationEngine, QUrl("qrc:/qml/BasicMessage.qml")); + QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); QObject* dialog = component.create(); dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); diff --git a/mix/ApplicationCtx.h b/mix/ApplicationCtx.h index 05e4f3bb3..5680c860e 100644 --- a/mix/ApplicationCtx.h +++ b/mix/ApplicationCtx.h @@ -42,7 +42,7 @@ class ApplicationCtx: public QObject public: ApplicationCtx(QQmlApplicationEngine* _engine); - ~ApplicationCtx(); + ~ApplicationCtx() {} static ApplicationCtx* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); @@ -53,7 +53,7 @@ public: private: static ApplicationCtx* Instance; - QQmlApplicationEngine* m_applicationEngine; + std::unique_ptr m_applicationEngine; std::unique_ptr m_webThree; std::unique_ptr m_keyEventManager; From de72fa0edd2ed8a6bbbf283607014244adcc4138 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 13:45:57 +0100 Subject: [PATCH 07/20] - fromRaw, fromString, prettyU256 moved to CommonJS.cpp. - ApplicationCtx => AppContext. - Smart pointer direct method call (instead of calling get() before). - ConstantCompilationModel instanciate as smart pointer. - Bug fix https://github.com/ethereum/cpp-ethereum/issues/557 - Add comments on DebuggingStateWrapper - Coding Standards --- alethzero/MainWin.cpp | 16 ++--- alethzero/MainWin.h | 8 ++- libdevcore/CommonJS.cpp | 70 ++++++++++++++++++++++ libdevcore/CommonJS.h | 7 ++- mix/{ApplicationCtx.cpp => AppContext.cpp} | 32 +++++----- mix/{ApplicationCtx.h => AppContext.h} | 17 +++--- mix/AssemblyDebuggerCtrl.cpp | 15 ++--- mix/AssemblyDebuggerModel.cpp | 8 +-- mix/CodeEditorExtensionManager.cpp | 10 ++-- mix/ConstantCompilationCtrl.cpp | 7 +-- mix/ConstantCompilationCtrl.h | 4 +- mix/ConstantCompilationModel.cpp | 4 +- mix/ConstantCompilationModel.h | 4 +- mix/DebuggingStateWrapper.cpp | 62 ++----------------- mix/DebuggingStateWrapper.h | 23 ++++--- mix/Extension.cpp | 8 +-- mix/TransactionBuilder.cpp | 58 +----------------- mix/TransactionBuilder.h | 36 +++++------ mix/main.cpp | 8 +-- 19 files changed, 183 insertions(+), 214 deletions(-) rename mix/{ApplicationCtx.cpp => AppContext.cpp} (73%) rename mix/{ApplicationCtx.h => AppContext.h} (80%) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 4a32f66b2..0fe55d320 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -64,7 +64,7 @@ static void initUnits(QComboBox* _b) _b->addItem(QString::fromStdString(units()[n].second), n); } -static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr) +QString Main::fromRaw(dev::h256 _n, unsigned* _inc) { if (_n) { @@ -148,7 +148,7 @@ Main::Main(QWidget *parent) : statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->blockCount); - + connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); @@ -173,17 +173,17 @@ Main::Main(QWidget *parent) : connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb)); connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString))); }); - + connect(ui->webView, &QWebView::loadFinished, [=]() { m_qweb->poll(); }); - + connect(ui->webView, &QWebView::titleChanged, [=]() { ui->tabWidget->setTabText(0, ui->webView->title()); }); - + readSettings(); installWatches(); startTimer(100); @@ -1067,7 +1067,7 @@ void Main::timerEvent(QTimerEvent*) // 7/18, Alex: aggregating timers, prelude to better threading? // Runs much faster on slower dual-core processors static int interval = 100; - + // refresh mining every 200ms if (interval / 100 % 2 == 0) refreshMining(); @@ -1093,7 +1093,7 @@ void Main::timerEvent(QTimerEvent*) } else interval += 100; - + if (m_qweb) m_qweb->poll(); @@ -1759,7 +1759,7 @@ void Main::on_net_triggered() { ui->port->setEnabled(!ui->net->isChecked()); ui->clientName->setEnabled(!ui->net->isChecked()); - string n = string("AlethZero/v") + dev::Version; + string n = string("AlethZero/v") + dev::Version; if (ui->clientName->text().size()) n += "/" + ui->clientName->text().toStdString(); n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 50b9df413..e4b40dd81 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -69,7 +69,7 @@ struct WorldState class Main : public QMainWindow { Q_OBJECT - + public: explicit Main(QWidget *parent = 0); ~Main(); @@ -79,7 +79,7 @@ public: std::shared_ptr whisper() const { return m_webThree->whisper(); } QList owned() const { return m_myIdentities + m_myKeys; } - + public slots: void load(QString _file); void note(QString _entry); @@ -146,7 +146,7 @@ private slots: void on_debugDumpState_triggered(int _add = 1); void on_debugDumpStatePre_triggered(); void on_refresh_triggered(); - void on_usePrivate_triggered(); + void on_usePrivate_triggered(); void on_enableOptimizer_triggered(); void on_turboMining_triggered(); void on_go_triggered(); @@ -259,4 +259,6 @@ private: QWebThreeConnector* m_qwebConnector; std::unique_ptr m_server; QWebThree* m_qweb = nullptr; + + static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr); }; diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index c09a5b565..800bd06c8 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -54,4 +54,74 @@ bytes unpadded(bytes _b) return _b; } +std::string prettyU256(u256 _n) +{ + unsigned inc = 0; + std::string raw; + std::ostringstream s; + if (!(_n >> 64)) + s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")"; + else if (!~(_n >> 64)) + s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")"; + else if ((_n >> 160) == 0) + { + Address a = right160(_n); + + std::string n = a.abridged(); + if (n.empty()) + s << "0x" << a; + else + s << n << "(0x" << a.abridged() << ")"; + } + else if ((raw = fromRaw((h256)_n, &inc)).size()) + return "\"" + raw + "\"" + (inc ? " + " + std::to_string(inc) : ""); + else + s << "" << (h256)_n; + return s.str(); +} + +std::string fromRaw(h256 _n, unsigned* _inc) +{ + if (_n) + { + std::string s((char const*)_n.data(), 32); + auto l = s.find_first_of('\0'); + if (!l) + return NULL; + if (l != std::string::npos) + { + auto p = s.find_first_not_of('\0', l); + if (!(p == std::string::npos || (_inc && p == 31))) + return NULL; + if (_inc) + *_inc = (byte)s[31]; + s.resize(l); + } + for (auto i: s) + if (i < 32) + return NULL; + return s; + } + return NULL; +} + +Address fromString(std::string _sn) +{ + if (_sn.size() > 32) + _sn.resize(32); + h256 n; + memcpy(n.data(), _sn.data(), _sn.size()); + memset(n.data() + _sn.size(), 0, 32 - _sn.size()); + if (_sn.size() == 40) + return Address(fromHex(_sn)); + else + return Address(); + //we try to resolve the recipient adress using nameReg contract state + /*const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract + if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) + if (h256 a = ethClient->stateAt(nameReg, n)) + return right160(a);*/ +} + + } diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 80e1a9ca1..0fb087f72 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -35,12 +35,12 @@ template std::string toJS(FixedHash const& _h) { return "0x" + toHex(_h.ref()); } - + template std::string toJS(boost::multiprecision::number> const& _n) { return "0x" + toHex(toCompactBigEndian(_n)); } - + inline std::string toJS(dev::bytes const& _n) { return "0x" + dev::toHex(_n); @@ -49,6 +49,9 @@ inline std::string toJS(dev::bytes const& _n) bytes jsToBytes(std::string const& _s); bytes padded(bytes _b, unsigned _l); bytes unpadded(bytes _s); +std::string prettyU256(u256 _n); +std::string fromRaw(h256 _n, unsigned* _inc = nullptr); +Address fromString(std::string _a); template FixedHash jsToFixed(std::string const& _s) { diff --git a/mix/ApplicationCtx.cpp b/mix/AppContext.cpp similarity index 73% rename from mix/ApplicationCtx.cpp rename to mix/AppContext.cpp index 0130f2dfb..5b8b76139 100644 --- a/mix/ApplicationCtx.cpp +++ b/mix/AppContext.cpp @@ -11,12 +11,12 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.cpp +/** @file AppContext.cpp * @author Yann yann@ethdev.com * @date 2014 - * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. - * For now ApplicationCtx provides reference to: + * For now AppContext provides reference to: * - QQmlApplicationEngine * - dev::WebThreeDirect (and dev::eth::Client) * - KeyEventManager @@ -28,58 +28,56 @@ #include #include "libdevcrypto/FileSystem.h" #include "KeyEventManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" using namespace dev; using namespace dev::mix; using namespace dev::eth; -ApplicationCtx* ApplicationCtx::Instance = nullptr; +AppContext* AppContext::Instance = nullptr; -ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) +AppContext::AppContext(QQmlApplicationEngine* _engine) { m_applicationEngine = std::unique_ptr(_engine); m_keyEventManager = std::unique_ptr(new KeyEventManager()); m_webThree = std::unique_ptr(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); } -QQmlApplicationEngine* ApplicationCtx::appEngine() +QQmlApplicationEngine* AppContext::appEngine() { return m_applicationEngine.get(); } -dev::eth::Client* ApplicationCtx::getEthereumClient() +dev::eth::Client* AppContext::getEthereumClient() { - return m_webThree.get()->ethereum(); + return m_webThree->ethereum(); } -void ApplicationCtx::initKeyEventManager() +void AppContext::initKeyEventManager() { QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); if (mainContent) - { QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); - } else qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!"; } -KeyEventManager* ApplicationCtx::getKeyEventManager() +KeyEventManager* AppContext::getKeyEventManager() { return m_keyEventManager.get(); } -void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) +void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) { if (Instance == nullptr) - Instance = new ApplicationCtx(_engine); + Instance = new AppContext(_engine); } -void ApplicationCtx::displayMessageDialog(QString _title, QString _message) +void AppContext::displayMessageDialog(QString _title, QString _message) { QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); QObject* dialog = component.create(); dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); - QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("title", _title); diff --git a/mix/ApplicationCtx.h b/mix/AppContext.h similarity index 80% rename from mix/ApplicationCtx.h rename to mix/AppContext.h index 5680c860e..da7bf9a8d 100644 --- a/mix/ApplicationCtx.h +++ b/mix/AppContext.h @@ -14,11 +14,12 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file AppContext.h * @author Yann yann@ethdev.com - * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. + * @date 2014 + * Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly. * In the future this class can be extended to add more variable related to the context of the application. - * For now ApplicationCtx provides reference to: + * For now AppContext provides reference to: * - QQmlApplicationEngine * - dev::WebThreeDirect (and dev::eth::Client) * - KeyEventManager @@ -36,14 +37,14 @@ namespace dev namespace mix { -class ApplicationCtx: public QObject +class AppContext: public QObject { Q_OBJECT public: - ApplicationCtx(QQmlApplicationEngine* _engine); - ~ApplicationCtx() {} - static ApplicationCtx* getInstance() { return Instance; } + AppContext(QQmlApplicationEngine* _engine); + ~AppContext() {} + static AppContext* getInstance() { return Instance; } static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); dev::eth::Client* getEthereumClient(); @@ -52,7 +53,7 @@ public: void displayMessageDialog(QString _title, QString _message); private: - static ApplicationCtx* Instance; + static AppContext* Instance; std::unique_ptr m_applicationEngine; std::unique_ptr m_webThree; std::unique_ptr m_keyEventManager; diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 94d8bf6cb..6e2b11e70 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -25,7 +25,7 @@ #include "AssemblyDebuggerCtrl.h" #include "TransactionBuilder.h" #include "KeyEventManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "DebuggingStateWrapper.h" using namespace dev::mix; @@ -48,16 +48,17 @@ QString AssemblyDebuggerCtrl::title() const void AssemblyDebuggerCtrl::start() const { //start to listen on F5 - ApplicationCtx::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); + AppContext::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); } void AssemblyDebuggerCtrl::keyPressed(int _key) { + if (_key == Qt::Key_F5) { if (!m_modelDebugger->compile(m_doc->toPlainText())) { - ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); + AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); return; } @@ -71,14 +72,14 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) QList wStates; for(int i = 0; i < debuggingContent.states.size(); i++) { - DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes()); + DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes(), this); s->setState(debuggingContent.states.at(i)); wStates.append(s); } std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); this->addContentOn(this); }; } diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index e4c2396ca..aa9795d53 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -22,7 +22,7 @@ #include "libethereum/ExtVM.h" #include "libevm/VM.h" #include "libdevcore/Common.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "TransactionBuilder.h" #include "AssemblyDebuggerModel.h" #include "ConstantCompilationModel.h" @@ -40,7 +40,7 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by { QList states; Transaction tr(_rawTransaction); - m_currentExecution.get()->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + m_currentExecution->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); std::vector levels; bytes code; bytesConstRef data; @@ -66,8 +66,8 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); }; - m_currentExecution.get()->go(onOp); - m_currentExecution.get()->finalize(onOp); + m_currentExecution->go(onOp); + m_currentExecution->finalize(onOp); DebuggingContent d; d.states = states; diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 3bef1a828..78b0f0a7f 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -28,7 +28,7 @@ #include #include "ConstantCompilationCtrl.h" #include "AssemblyDebuggerCtrl.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "CodeEditorExtensionManager.h" using namespace dev::mix; @@ -65,13 +65,13 @@ void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) { - if (!_ext.get()->contentUrl().isEmpty()) + if (!_ext->contentUrl().isEmpty()) { try { - if (_ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) + if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) { - _ext.get()->addTabOn(m_tabView); + _ext->addTabOn(m_tabView); } } catch (...) @@ -80,7 +80,7 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) return; } } - _ext.get()->start(); + _ext->start(); m_features.append(_ext); } diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index a703e6686..771387656 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -33,12 +33,7 @@ using namespace dev::mix; ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) { m_editor = _doc; - m_compilationModel = new ConstantCompilationModel(); -} - -ConstantCompilationCtrl::~ConstantCompilationCtrl() -{ - delete m_compilationModel; + m_compilationModel = std::unique_ptr(new ConstantCompilationModel()); } QString ConstantCompilationCtrl::contentUrl() const diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index e4661c800..446838d39 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -35,14 +35,14 @@ class ConstantCompilationCtrl: public Extension public: ConstantCompilationCtrl(QTextDocument*); - ~ConstantCompilationCtrl(); + ~ConstantCompilationCtrl() {} void start() const override; QString title() const override; QString contentUrl() const override; private: QTextDocument* m_editor; - ConstantCompilationModel* m_compilationModel; + std::unique_ptr m_compilationModel; void writeOutPut(CompilerResult const&); void resetOutPut(); diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index a6b2f2741..f50ac805b 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -49,7 +49,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) ostringstream error; solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler.getScanner()); res.success = false; - res.comment = QString::fromStdString(error.str()).toHtmlEscaped(); + res.comment = QString::fromStdString(error.str()); res.hexCode = ""; } catch (...) diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 713c9e950..465cba285 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -45,7 +45,7 @@ class ConstantCompilationModel public: ConstantCompilationModel() {} ~ConstantCompilationModel() {} - CompilerResult compile(QString); + CompilerResult compile(QString _code); }; } diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index d96c975cd..2dde93520 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingState.h +/** @file DebuggingStateWrapper.h * @author Yann yann@ethdev.com * @date 2014 * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). @@ -23,6 +23,7 @@ #include #include #include +#include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" #include "libevmcore/Instruction.h" #include "libdevcore/Common.h" @@ -68,7 +69,7 @@ QString DebuggingStateWrapper::debugStack() { QString stack; for (auto i: m_state.stack) - stack.prepend(prettyU256(i) + "\n"); + stack.prepend(QString::fromStdString(prettyU256(i)) + "\n"); return stack; } @@ -77,7 +78,7 @@ QString DebuggingStateWrapper::debugStorage() { std::stringstream s; for (auto const& i: m_state.storage) - s << "@" << prettyU256(i.first).toStdString() << "    " << prettyU256(i.second).toStdString(); + s << "@" << prettyU256(i.first) << "    " << prettyU256(i.second); return QString::fromStdString(s.str()); } @@ -130,60 +131,9 @@ QString DebuggingStateWrapper::endOfDebug() return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return "STOP"; + return "STOP"; else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else return "EXCEPTION"; } - -QString DebuggingStateWrapper::prettyU256(u256 _n) -{ - unsigned inc = 0; - QString raw; - std::ostringstream s; - if (!(_n >> 64)) - s << " " << (uint64_t)_n << " (0x" << hex << (uint64_t)_n << ")"; - else if (!~(_n >> 64)) - s << " " << (int64_t)_n << " (0x" << hex << (int64_t)_n << ")"; - else if ((_n >> 160) == 0) - { - Address a = right160(_n); - - QString n = QString::fromStdString(a.abridged());//pretty(a); - if (n.isNull()) - s << "0x" << a; - else - s << n.toHtmlEscaped().toStdString() << "(0x" << a.abridged() << ")"; - } - else if ((raw = fromRaw((h256)_n, &inc)).size()) - return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : ""); - else - s << "" << (h256)_n; - return QString::fromStdString(s.str()); -} - -QString DebuggingStateWrapper::fromRaw(h256 _n, unsigned* _inc) -{ - if (_n) - { - std::string s((char const*)_n.data(), 32); - auto l = s.find_first_of('\0'); - if (!l) - return QString(); - if (l != std::string::npos) - { - auto p = s.find_first_not_of('\0', l); - if (!(p == std::string::npos || (_inc && p == 31))) - return QString(); - if (_inc) - *_inc = (byte)s[31]; - s.resize(l); - } - for (auto i: s) - if (i < 32) - return QString(); - return QString::fromStdString(s); - } - return QString(); -} diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 3f03004b8..df3b8ccce 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingState.h +/** @file DebuggingStateWrapper.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. @@ -57,7 +57,9 @@ struct DebuggingContent QString message; }; -/* contains the line nb of the assembly code and the corresponding index in the code bytes array */ +/** + * @brief Contains the line nb of the assembly code and the corresponding index in the code bytes array. + */ class HumanReadableCode: public QObject { Q_OBJECT @@ -74,20 +76,25 @@ private: int m_processIndex; }; -/* used to publish QMap type to QML */ + +/** + * @brief Publish QMap type to QML. + */ class QQMLMap: public QObject { Q_OBJECT public: - QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } - Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + QQMLMap(QMap _map, QObject* _parent): QObject(_parent), m_map(_map) { } + Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } private: QMap m_map; }; -/* used to publish DebuggingState struct to QML */ +/** + * @brief Wrap DebuggingState in QObject + */ class DebuggingStateWrapper: public QObject { Q_OBJECT @@ -104,7 +111,7 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList levels READ levels) public: - DebuggingStateWrapper(bytes _code, bytes _data) : m_code(_code), m_data(_data) {} + DebuggingStateWrapper(bytes _code, bytes _data, QObject* parent): QObject(parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } int gasCost() { return (int)m_state.gasCost; } @@ -124,8 +131,6 @@ private: DebuggingState m_state; bytes m_code; bytes m_data; - QString prettyU256(u256 _n); - QString fromRaw(h256 _n, unsigned* _inc = nullptr); }; } diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 24cc19aba..410fe85ec 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -21,7 +21,7 @@ #include #include #include "Extension.h" -#include "ApplicationCtx.h" +#include "AppContext.h" using namespace dev; using namespace dev::mix; @@ -32,7 +32,7 @@ void Extension::addTabOn(QObject* _view) QVariant returnValue; QQmlComponent* component = new QQmlComponent( - ApplicationCtx::getInstance()->appEngine(), + AppContext::getInstance()->appEngine(), QUrl(contentUrl()), _view); QMetaObject::invokeMethod(_view, "addTab", @@ -48,9 +48,9 @@ void Extension::addContentOn(QObject* _view) Q_UNUSED(_view); if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) { - QQmlComponent component(ApplicationCtx::getInstance()->appEngine(), QUrl(contentUrl())); + QQmlComponent component(AppContext::getInstance()->appEngine(), QUrl(contentUrl())); QObject* dialog = component.create(); - QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("title", title()); diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp index ce274fa00..bb7cda939 100644 --- a/mix/TransactionBuilder.cpp +++ b/mix/TransactionBuilder.cpp @@ -18,8 +18,9 @@ */ #include "libethereum/Executive.h" +#include "libdevcore/CommonJS.h" #include "libdevcore/Common.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "TransactionBuilder.h" using namespace dev::mix; using namespace dev::eth; @@ -34,59 +35,6 @@ Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPri Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, QString address, bytes _data, u256 _nonce, Secret _secret) const { - return Transaction(_value, _gasPrice, _gas, fromString(address), _data, _nonce, _secret); + return Transaction(_value, _gasPrice, _gas, dev::fromString(address.toStdString()), _data, _nonce, _secret); } -int TransactionBuilder::fromHex(char _i) const -{ - if (_i >= '0' && _i <= '9') - return _i - '0'; - if (_i >= 'a' && _i <= 'f') - return _i - 'a' + 10; - if (_i >= 'A' && _i <= 'F') - return _i - 'A' + 10; - BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i)); -} - -bytes TransactionBuilder::fromHex(std::string const& _s) const -{ - unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0; - std::vector ret; - ret.reserve((_s.size() - s + 1) / 2); - - if (_s.size() % 2) - try - { - ret.push_back(fromHex(_s[s++])); - } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } - for (unsigned i = s; i < _s.size(); i += 2) - try - { - ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1]))); - } - catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); } - return ret; -} - -Address TransactionBuilder::fromString(QString const& _a) const -{ - Client* ethClient = ApplicationCtx::getInstance()->getEthereumClient(); - std::string sn = _a.toStdString(); - if (sn.size() > 32) - sn.resize(32); - h256 n; - memcpy(n.data(), sn.data(), sn.size()); - memset(n.data() + sn.size(), 0, 32 - sn.size()); - if (_a.size() == 40) - return Address(fromHex(_a.toStdString())); - else - { - //we try to resolve the recipient adress using nameReg contract state - const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract - if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) - if (h256 a = ethClient->stateAt(nameReg, n)) - return right160(a); - } - return Address(); // should maybe throws exception instead of returning blank address. -} diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h index 261d3060f..99f65b024 100644 --- a/mix/TransactionBuilder.h +++ b/mix/TransactionBuilder.h @@ -1,15 +1,15 @@ /* - This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + This file is part of cpp-ethereum. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file TransactionBuilder.h * @author Yann yann@ethdev.com @@ -32,15 +32,11 @@ namespace mix class TransactionBuilder { public: - TransactionBuilder() {} - dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; - dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - dev::bytes _data, dev::u256 _nonce, Secret _secret) const; -private: - bytes fromHex(std::string const& _s) const; - int fromHex(char _i) const; - Address fromString(QString const& _a) const; + TransactionBuilder() {} + dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + QString address, bytes _data, dev::u256 _nonce, Secret _secret) const; + dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, + dev::bytes _data, dev::u256 _nonce, Secret _secret) const; }; } diff --git a/mix/main.cpp b/mix/main.cpp index 4f707f47a..33a139f85 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -24,7 +24,7 @@ #include #include #include "CodeEditorExtensionManager.h" -#include "ApplicationCtx.h" +#include "AppContext.h" #include "MixApplication.h" using namespace dev::mix; @@ -33,11 +33,11 @@ int main(int _argc, char *_argv[]) QApplication app(_argc, _argv); qmlRegisterType("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); QQmlApplicationEngine* engine = new QQmlApplicationEngine(); - ApplicationCtx::setApplicationContext(engine); - QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff + AppContext::setApplicationContext(engine); + QObject::connect(&app, SIGNAL(lastWindowClosed()), AppContext::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - ApplicationCtx::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. + AppContext::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. return app.exec(); } From 7e44c34491a62cba5ecef5253404e0a25241a74b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 15:41:22 +0100 Subject: [PATCH 08/20] - manage Debugger states calculation in a separate thread (avoid blocking the UI) --- mix/AssemblyDebuggerCtrl.cpp | 25 +++++++++++++++++++------ mix/AssemblyDebuggerCtrl.h | 8 ++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 6e2b11e70..4d293cd8d 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -17,6 +17,7 @@ * display opcode debugging. */ +#include #include #include #include @@ -31,6 +32,9 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { + qRegisterMetaType(); + connect(this, SIGNAL(dataAvailable(QList, AssemblyDebuggerData)), + this, SLOT(updateGUI(QList, AssemblyDebuggerData)), Qt::QueuedConnection); m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); m_doc = _doc; } @@ -56,6 +60,9 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) if (_key == Qt::Key_F5) { + QString code = m_doc->toPlainText(); + QtConcurrent::run([this, code](){ + if (!m_modelDebugger->compile(m_doc->toPlainText())) { AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); @@ -76,10 +83,16 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) s->setState(debuggingContent.states.at(i)); wStates.append(s); } - std::tuple, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); - this->addContentOn(this); - }; + AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); + emit dataAvailable(wStates, code); + }); + } +} + +void AssemblyDebuggerCtrl::updateGUI(QList _wStates, AssemblyDebuggerData _code) +{ + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + this->addContentOn(this); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index a1642cc14..66256e472 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -25,6 +25,9 @@ #include "ConstantCompilationModel.h" #include "AssemblyDebuggerModel.h" +using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; +Q_DECLARE_METATYPE(AssemblyDebuggerData) + namespace dev { @@ -48,6 +51,11 @@ private: public Q_SLOTS: void keyPressed(int); + void updateGUI(QList _wStates, AssemblyDebuggerData _code); + +signals: + void dataAvailable(QList _wStates, AssemblyDebuggerData _code); + }; } From 0d58c2b664d880253d93a1ec0b10c36f3ee03f6b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 16:53:07 +0100 Subject: [PATCH 09/20] - delete code comment (code used to resolve name using NameReg contract) --- libdevcore/CommonJS.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 800bd06c8..8d8638da5 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -116,11 +116,6 @@ Address fromString(std::string _sn) return Address(fromHex(_sn)); else return Address(); - //we try to resolve the recipient adress using nameReg contract state - /*const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract - if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0)) - if (h256 a = ethClient->stateAt(nameReg, n)) - return right160(a);*/ } From 6030db73f771bc6edb8dcb4837464ffa5456df7b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 17:42:47 +0100 Subject: [PATCH 10/20] - Bug fix (failed compilation alert was loaded in a separate thread). - Coding Standards. - Add DebuggingStatusResult in AssemblyDebuggerCtrl --- mix/AssemblyDebuggerCtrl.cpp | 25 ++++++++++++++++--------- mix/AssemblyDebuggerCtrl.h | 11 +++++++++-- mix/AssemblyDebuggerModel.cpp | 4 ++-- mix/DebuggingStateWrapper.h | 4 ++-- mix/KeyEventManager.h | 6 +++--- mix/TransactionBuilder.cpp | 4 ++-- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 4d293cd8d..e48aa9138 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -33,8 +33,9 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { qRegisterMetaType(); - connect(this, SIGNAL(dataAvailable(QList, AssemblyDebuggerData)), - this, SLOT(updateGUI(QList, AssemblyDebuggerData)), Qt::QueuedConnection); + qRegisterMetaType(); + connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), + this, SLOT(updateGUI(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), Qt::QueuedConnection); m_modelDebugger = std::unique_ptr(new AssemblyDebuggerModel); m_doc = _doc; } @@ -65,7 +66,7 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) if (!m_modelDebugger->compile(m_doc->toPlainText())) { - AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); + emit dataAvailable(false, DebuggingStatusResult::Compilationfailed); return; } @@ -84,15 +85,21 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) wStates.append(s); } AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); - emit dataAvailable(wStates, code); + emit dataAvailable(true, DebuggingStatusResult::Ok, wStates, code); }); } } -void AssemblyDebuggerCtrl::updateGUI(QList _wStates, AssemblyDebuggerData _code) +void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList _wStates, AssemblyDebuggerData _code) { - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); - this->addContentOn(this); + Q_UNUSED(reason); + if (success) + { + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + this->addContentOn(this); + } + else + AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 66256e472..0c092c46d 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -26,7 +26,14 @@ #include "AssemblyDebuggerModel.h" using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; +enum DebuggingStatusResult +{ + Ok, + Compilationfailed +}; + Q_DECLARE_METATYPE(AssemblyDebuggerData) +Q_DECLARE_METATYPE(DebuggingStatusResult) namespace dev { @@ -51,10 +58,10 @@ private: public Q_SLOTS: void keyPressed(int); - void updateGUI(QList _wStates, AssemblyDebuggerData _code); + void updateGUI(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); signals: - void dataAvailable(QList _wStates, AssemblyDebuggerData _code); + void dataAvailable(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); }; diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index aa9795d53..bcf58835c 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -81,11 +81,11 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, - QString code, + QString _code, KeyPair _key) { ConstantCompilationModel compiler; - CompilerResult res = compiler.compile(code); + CompilerResult res = compiler.compile(_code); if (!res.success) { DebuggingContent r; diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index df3b8ccce..89f90bfbd 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -111,7 +111,7 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList levels READ levels) public: - DebuggingStateWrapper(bytes _code, bytes _data, QObject* parent): QObject(parent), m_code(_code), m_data(_data) {} + DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } int gasCost() { return (int)m_state.gasCost; } @@ -125,7 +125,7 @@ public: QStringList levels(); DebuggingState state() { return m_state; } void setState(DebuggingState _state) { m_state = _state; } - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& code, QObject* _objUsedAsParent); + static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& _code, QObject* _objUsedAsParent); private: DebuggingState m_state; diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h index ecd768c4c..32ee5e867 100644 --- a/mix/KeyEventManager.h +++ b/mix/KeyEventManager.h @@ -30,13 +30,13 @@ class KeyEventManager: public QObject public: KeyEventManager() {} - void registerEvent(const QObject* receiver, const char* slot); - void unRegisterEvent(QObject* receiver); + void registerEvent(const QObject* _receiver, const char* _slot); + void unRegisterEvent(QObject* _receiver); signals: void onKeyPressed(int); public Q_SLOTS: - void keyPressed(QVariant event); + void keyPressed(QVariant _event); }; diff --git a/mix/TransactionBuilder.cpp b/mix/TransactionBuilder.cpp index bb7cda939..68eecf10b 100644 --- a/mix/TransactionBuilder.cpp +++ b/mix/TransactionBuilder.cpp @@ -33,8 +33,8 @@ Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPri } Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas, - QString address, bytes _data, u256 _nonce, Secret _secret) const + QString _address, bytes _data, u256 _nonce, Secret _secret) const { - return Transaction(_value, _gasPrice, _gas, dev::fromString(address.toStdString()), _data, _nonce, _secret); + return Transaction(_value, _gasPrice, _gas, dev::fromString(_address.toStdString()), _data, _nonce, _secret); } From 421506a8695b39ab50743eb386c7f160f8bcf360 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 19:49:44 +0100 Subject: [PATCH 11/20] - Coding Standards. - Q_SLOTS => slots. - https://github.com/ethereum/cpp-ethereum/issues/557 => replace by 8 spaces instead of 4. - ref to QtQuick 2.2 instead of 2.3 --- mix/AppContext.h | 1 - mix/AssemblyDebuggerCtrl.cpp | 4 ++-- mix/AssemblyDebuggerCtrl.h | 3 +-- mix/AssemblyDebuggerModel.h | 1 - mix/CodeEditorExtensionManager.cpp | 2 -- mix/CodeEditorExtensionManager.h | 1 - mix/ConstantCompilationCtrl.cpp | 2 +- mix/ConstantCompilationCtrl.h | 3 +-- mix/ConstantCompilationModel.h | 1 - mix/DebuggingStateWrapper.cpp | 1 - mix/DebuggingStateWrapper.h | 1 - mix/Extension.h | 1 - mix/KeyEventManager.h | 2 +- mix/MixApplication.h | 1 - mix/TransactionBuilder.h | 1 - mix/qml/BasicMessage.qml | 2 +- mix/qml/Debugger.qml | 2 +- mix/qml/MainContent.qml | 2 +- 18 files changed, 9 insertions(+), 22 deletions(-) diff --git a/mix/AppContext.h b/mix/AppContext.h index da7bf9a8d..0016ab3be 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -33,7 +33,6 @@ namespace dev { - namespace mix { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index e48aa9138..18e5802af 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -58,11 +58,11 @@ void AssemblyDebuggerCtrl::start() const void AssemblyDebuggerCtrl::keyPressed(int _key) { - if (_key == Qt::Key_F5) { QString code = m_doc->toPlainText(); - QtConcurrent::run([this, code](){ + QtConcurrent::run([this, code]() + { if (!m_modelDebugger->compile(m_doc->toPlainText())) { diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 0c092c46d..1976b2d64 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -37,7 +37,6 @@ Q_DECLARE_METATYPE(DebuggingStatusResult) namespace dev { - namespace mix { @@ -56,7 +55,7 @@ private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; -public Q_SLOTS: +public slots: void keyPressed(int); void updateGUI(bool success, DebuggingStatusResult reason, QList _wStates = QList(), AssemblyDebuggerData _code = AssemblyDebuggerData()); diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index c0941dc8f..3ed6818bc 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -28,7 +28,6 @@ namespace dev { - namespace mix { diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 78b0f0a7f..1b2a9cc3c 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -70,9 +70,7 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr _ext) try { if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) - { _ext->addTabOn(m_tabView); - } } catch (...) { diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 8e8501bc9..84ce9af92 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -30,7 +30,6 @@ namespace dev { - namespace mix { diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 771387656..8b0577d93 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -59,7 +59,7 @@ void ConstantCompilationCtrl::compile() resetOutPut(); return; } - CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); + CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); writeOutPut(res); } diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index 446838d39..7cde63a05 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -25,7 +25,6 @@ namespace dev { - namespace mix { @@ -46,7 +45,7 @@ private: void writeOutPut(CompilerResult const&); void resetOutPut(); -public Q_SLOTS: +public slots: void compile(); }; diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 465cba285..4c161ec09 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -27,7 +27,6 @@ namespace dev { - namespace mix { diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 2dde93520..89d9892ac 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -90,7 +90,6 @@ QString DebuggingStateWrapper::debugMemory() QString DebuggingStateWrapper::debugCallData() { - return QString::fromStdString(memDump(m_data, 16, false)); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 89f90bfbd..09089fe58 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -29,7 +29,6 @@ namespace dev { - namespace mix { diff --git a/mix/Extension.h b/mix/Extension.h index b697af58b..b6a65bb5f 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -24,7 +24,6 @@ namespace dev { - namespace mix { diff --git a/mix/KeyEventManager.h b/mix/KeyEventManager.h index 32ee5e867..f3343cc45 100644 --- a/mix/KeyEventManager.h +++ b/mix/KeyEventManager.h @@ -36,7 +36,7 @@ public: signals: void onKeyPressed(int); -public Q_SLOTS: +public slots: void keyPressed(QVariant _event); }; diff --git a/mix/MixApplication.h b/mix/MixApplication.h index fdc506268..d927f2e07 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -27,7 +27,6 @@ namespace dev { - namespace mix { diff --git a/mix/TransactionBuilder.h b/mix/TransactionBuilder.h index 99f65b024..9ad929d38 100644 --- a/mix/TransactionBuilder.h +++ b/mix/TransactionBuilder.h @@ -25,7 +25,6 @@ namespace dev { - namespace mix { diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 14ddbcf0d..0678c9b54 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 6802f57df..e895d1ada 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 821b48913..1da48a1c8 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Layouts 1.0 import QtQuick.Controls.Styles 1.2 From c9bf5fcd7c6fef8fba3982f853c429cbf16403cf Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 21:32:05 +0100 Subject: [PATCH 12/20] - Instruction.h: add functions "getInstructionNumber" - AssemblyDebuggerCtrl add members AppContext, QQMLApplicationEngine --- libevmcore/Instruction.h | 18 ++++++++++++++++++ mix/AssemblyDebuggerCtrl.cpp | 12 +++++++----- mix/AssemblyDebuggerCtrl.h | 3 +++ mix/DebuggingStateWrapper.cpp | 3 ++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index f8a0478f1..555dbf0ea 100644 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -173,6 +173,24 @@ enum class Instruction: uint8_t SUICIDE = 0xff ///< halt execution and register account for later deletion }; +/// @returns the number of PUSH Instruction _inst +inline unsigned getPushNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::PUSH1) + 1; +} + +/// @returns the number of DUP Instruction _inst +inline unsigned getDupNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::DUP1) + 1; +} + +/// @returns the number of SWAP Instruction _inst +inline unsigned getSwapNumber(Instruction _inst) +{ + return (byte)_inst - unsigned(Instruction::SWAP1) + 1; +} + /// @returns the PUSH<_number> instruction inline Instruction pushInstruction(unsigned _number) { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 18e5802af..1fdb9403e 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -32,6 +32,8 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { + m_ctx = AppContext::getInstance(); + m_appEngine = m_ctx->appEngine(); qRegisterMetaType(); qRegisterMetaType(); connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), @@ -53,7 +55,7 @@ QString AssemblyDebuggerCtrl::title() const void AssemblyDebuggerCtrl::start() const { //start to listen on F5 - AppContext::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); + m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); } void AssemblyDebuggerCtrl::keyPressed(int _key) @@ -95,11 +97,11 @@ void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, Q_UNUSED(reason); if (success) { - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); - AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); + m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates)); + m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code))); + m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code))); this->addContentOn(this); } else - AppContext::getInstance()->displayMessageDialog("debugger","compilation failed"); + m_ctx->displayMessageDialog("debugger","compilation failed"); } diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index 1976b2d64..b4957ed85 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -24,6 +24,7 @@ #include "Extension.h" #include "ConstantCompilationModel.h" #include "AssemblyDebuggerModel.h" +#include "AppContext.h" using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; enum DebuggingStatusResult @@ -54,6 +55,8 @@ public: private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; + AppContext* m_ctx; + QQmlApplicationEngine* m_appEngine; public slots: void keyPressed(int); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 89d9892ac..6328cce6b 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -23,6 +23,7 @@ #include #include #include +#include "libevmcore/Instruction.h" #include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" #include "libevmcore/Instruction.h" @@ -48,7 +49,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod int line = i; if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) { - unsigned bc = b - (byte)Instruction::PUSH1 + 1; + unsigned bc = getPushNumber((Instruction)b); s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } From dee70471980d59b3a8b97b677a1bd0051839984f Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 8 Dec 2014 21:56:17 +0100 Subject: [PATCH 13/20] - QQMLApplicationEngine and AppContext moved to Extension.h --- mix/AssemblyDebuggerCtrl.cpp | 2 -- mix/AssemblyDebuggerCtrl.h | 2 -- mix/DebuggingStateWrapper.cpp | 2 +- mix/Extension.cpp | 17 +++++++++++++++++ mix/Extension.h | 10 ++++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 1fdb9403e..36318ccb7 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -32,8 +32,6 @@ using namespace dev::mix; AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) { - m_ctx = AppContext::getInstance(); - m_appEngine = m_ctx->appEngine(); qRegisterMetaType(); qRegisterMetaType(); connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList, AssemblyDebuggerData)), diff --git a/mix/AssemblyDebuggerCtrl.h b/mix/AssemblyDebuggerCtrl.h index b4957ed85..e94cc4ce9 100644 --- a/mix/AssemblyDebuggerCtrl.h +++ b/mix/AssemblyDebuggerCtrl.h @@ -55,8 +55,6 @@ public: private: std::unique_ptr m_modelDebugger; QTextDocument* m_doc; - AppContext* m_ctx; - QQmlApplicationEngine* m_appEngine; public slots: void keyPressed(int); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 6328cce6b..2315cd5a8 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file DebuggingStateWrapper.h +/** @file DebuggingStateWrapper.cpp * @author Yann yann@ethdev.com * @date 2014 * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 410fe85ec..f9a8ad94d 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -25,6 +25,23 @@ using namespace dev; using namespace dev::mix; +Extension::Extension() +{ + init(); +} + +Extension::Extension(ExtensionDisplayBehavior _displayBehavior) +{ + init(); + m_displayBehavior = _displayBehavior; +} + +void Extension::init() +{ + m_ctx = AppContext::getInstance(); + m_appEngine = m_ctx->appEngine(); +} + void Extension::addTabOn(QObject* _view) { if (contentUrl() == "") diff --git a/mix/Extension.h b/mix/Extension.h index b6a65bb5f..4d6f4f084 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -21,6 +21,7 @@ #include #include +#include "AppContext.h" namespace dev { @@ -39,8 +40,8 @@ class Extension: public QObject Q_OBJECT public: - Extension() {} - Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } + Extension(); + Extension(ExtensionDisplayBehavior _displayBehavior); virtual QString contentUrl() const { return ""; } virtual QString title() const { return ""; } virtual void start() const {} @@ -52,6 +53,11 @@ public: protected: QObject* m_view; ExtensionDisplayBehavior m_displayBehavior; + AppContext* m_ctx; + QQmlApplicationEngine* m_appEngine; + +private: + void init(); }; } From 5f4627043da856068a82b482ba76c46e2a3c26f4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 9 Dec 2014 09:39:46 +0100 Subject: [PATCH 14/20] - returning empty string instead of NULL --- libdevcore/CommonJS.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 8d8638da5..9dc04b7e7 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -87,22 +87,22 @@ std::string fromRaw(h256 _n, unsigned* _inc) std::string s((char const*)_n.data(), 32); auto l = s.find_first_of('\0'); if (!l) - return NULL; + return ""; if (l != std::string::npos) { auto p = s.find_first_not_of('\0', l); if (!(p == std::string::npos || (_inc && p == 31))) - return NULL; + return ""; if (_inc) *_inc = (byte)s[31]; s.resize(l); } for (auto i: s) if (i < 32) - return NULL; + return ""; return s; } - return NULL; + return ""; } Address fromString(std::string _sn) From 4da294f86d984efb60293a979b703722f2785e9a Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 12 Dec 2014 14:01:26 +0100 Subject: [PATCH 15/20] - CommonJS => fromString(string _sn) fromString(string const& _sn). - Wrapping string with QApplication::tr(), used for localization. --- libdevcore/CommonJS.cpp | 7 +------ libdevcore/CommonJS.h | 2 +- mix/AssemblyDebuggerCtrl.cpp | 5 ++--- mix/AssemblyDebuggerModel.cpp | 3 ++- mix/ConstantCompilationCtrl.cpp | 6 +++--- mix/ConstantCompilationModel.cpp | 3 ++- mix/KeyEventManager.cpp | 2 -- 7 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 9dc04b7e7..ad3ade71f 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -105,13 +105,8 @@ std::string fromRaw(h256 _n, unsigned* _inc) return ""; } -Address fromString(std::string _sn) +Address fromString(std::string const& _sn) { - if (_sn.size() > 32) - _sn.resize(32); - h256 n; - memcpy(n.data(), _sn.data(), _sn.size()); - memset(n.data() + _sn.size(), 0, 32 - _sn.size()); if (_sn.size() == 40) return Address(fromHex(_sn)); else diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 0fb087f72..8b96b2e68 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -51,7 +51,7 @@ bytes padded(bytes _b, unsigned _l); bytes unpadded(bytes _s); std::string prettyU256(u256 _n); std::string fromRaw(h256 _n, unsigned* _inc = nullptr); -Address fromString(std::string _a); +Address fromString(std::string const& _a); template FixedHash jsToFixed(std::string const& _s) { diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 36318ccb7..678f94d77 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -47,7 +47,7 @@ QString AssemblyDebuggerCtrl::contentUrl() const QString AssemblyDebuggerCtrl::title() const { - return "debugger"; + return QApplication::tr("debugger"); } void AssemblyDebuggerCtrl::start() const @@ -63,7 +63,6 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) QString code = m_doc->toPlainText(); QtConcurrent::run([this, code]() { - if (!m_modelDebugger->compile(m_doc->toPlainText())) { emit dataAvailable(false, DebuggingStatusResult::Compilationfailed); @@ -101,5 +100,5 @@ void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, this->addContentOn(this); } else - m_ctx->displayMessageDialog("debugger","compilation failed"); + m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed")); } diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index bcf58835c..ad6ba156d 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -17,6 +17,7 @@ * used as a model to debug contract assembly code. */ +#include #include "libethereum/Executive.h" #include "libethereum/Transaction.h" #include "libethereum/ExtVM.h" @@ -90,7 +91,7 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 { DebuggingContent r; r.contentAvailable = false; - r.message = "compile failed"; + r.message = QApplication::tr("compilation failed"); return r; } diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 8b0577d93..3ccd87f77 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -43,7 +43,7 @@ QString ConstantCompilationCtrl::contentUrl() const QString ConstantCompilationCtrl::title() const { - return "compiler"; + return QApplication::tr("compiler"); } void ConstantCompilationCtrl::start() const @@ -80,13 +80,13 @@ void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res) status->setProperty("text", "succeeded"); status->setProperty("color", "green"); content->setProperty("text", _res.hexCode); - qDebug() << QString("compile succeeded " + _res.hexCode); + qDebug() << QString(QApplication::tr("compile succeeded") + " " + _res.hexCode); } else { status->setProperty("text", "failure"); status->setProperty("color", "red"); content->setProperty("text", _res.comment); - qDebug() << QString("compile failed " + _res.comment); + qDebug() << QString(QApplication::tr("compile failed") + " " + _res.comment); } } diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index f50ac805b..817d01635 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -20,6 +20,7 @@ * Ethereum IDE client. */ +#include #include #include #include @@ -55,7 +56,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code) catch (...) { res.success = false; - res.comment = "Uncaught exception."; + res.comment = QApplication::tr("Uncaught exception."); res.hexCode = ""; } return res; diff --git a/mix/KeyEventManager.cpp b/mix/KeyEventManager.cpp index f5d638869..c32caadb8 100644 --- a/mix/KeyEventManager.cpp +++ b/mix/KeyEventManager.cpp @@ -39,5 +39,3 @@ void KeyEventManager::keyPressed(QVariant _event) { emit onKeyPressed(_event.toInt()); } - - From d76b3f472e1751ec3f4d080c16bdaf1fe7e3b1e0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 09:57:10 +0100 Subject: [PATCH 16/20] - Send String value to QML instead of int value (gas, gasCost, gasLeft). - Wrap label with QApplication::tr (localization). - Use of std::hex, std::dec instead of QTextStream (to avoid warning). --- mix/DebuggingStateWrapper.cpp | 41 +++++++++++++++++++++++++---------- mix/DebuggingStateWrapper.h | 10 +++++---- mix/qml/js/Debugger.js | 5 ++--- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 2315cd5a8..36b098379 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -20,9 +20,8 @@ * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). */ +#include #include -#include -#include #include "libevmcore/Instruction.h" #include "libdevcore/CommonJS.h" #include "libdevcrypto/Common.h" @@ -44,7 +43,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod { QString s = QString::fromStdString(instructionInfo((Instruction)b).name); std::ostringstream out; - out << hex << std::setw(4) << std::setfill('0') << i; + out << std::hex << std::setw(4) << std::setfill('0') << i; codeMapping[i] = codeStr.size(); int line = i; if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) @@ -66,6 +65,27 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent)); } +QString DebuggingStateWrapper::gasLeft() +{ + std::ostringstream ss; + ss << std::dec << (m_state.gas - m_state.gasCost); + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::gasCost() +{ + std::ostringstream ss; + ss << std::dec << m_state.gasCost; + return QString::fromStdString(ss.str()); +} + +QString DebuggingStateWrapper::gas() +{ + std::ostringstream ss; + ss << std::dec << m_state.gas; + return QString::fromStdString(ss.str()); +} + QString DebuggingStateWrapper::debugStack() { QString stack; @@ -99,11 +119,10 @@ QStringList DebuggingStateWrapper::levels() QStringList levelsStr; for (unsigned i = 0; i <= m_state.levels.size(); ++i) { - DebuggingState const& s = i ? *m_state.levels[m_state.levels.size() - i] : m_state; std::ostringstream out; out << m_state.cur.abridged(); if (i) - out << " " << instructionInfo(m_state.inst).name << " @0x" << hex << m_state.curPC; + out << " " << instructionInfo(m_state.inst).name << " @0x" << std::hex << m_state.curPC; levelsStr.append(QString::fromStdString(out.str())); } return levelsStr; @@ -112,14 +131,14 @@ QStringList DebuggingStateWrapper::levels() QString DebuggingStateWrapper::headerInfo() { std::ostringstream ss; - ss << dec << " STEP: " << m_state.steps << " | PC: 0x" << hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << dec << m_state.newMemSize << " words | COST: " << dec << m_state.gasCost << " | GAS: " << dec << m_state.gas; + ss << std::dec << " " << QApplication::tr("STEP").toStdString() << " : " << m_state.steps << " | PC: 0x" << std::hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << std::dec << m_state.newMemSize << " " << QApplication::tr("words").toStdString() << " | " << QApplication::tr("COST").toStdString() << " : " << std::dec << m_state.gasCost << " | " << QApplication::tr("GAS").toStdString() << " : " << std::dec << m_state.gas; return QString::fromStdString(ss.str()); } QString DebuggingStateWrapper::endOfDebug() { if (m_state.gasCost > m_state.gas) - return "OUT-OF-GAS"; + return QApplication::tr("OUT-OF-GAS"); else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) { unsigned from = (unsigned)m_state.stack.back(); @@ -128,12 +147,12 @@ QString DebuggingStateWrapper::endOfDebug() bytes out(size, 0); for (; o < size && from + o < m_state.memory.size(); ++o) out[o] = m_state.memory[from + o]; - return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); + return QApplication::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return "STOP"; + return QApplication::tr("STOP"); else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return QApplication::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else - return "EXCEPTION"; + return QApplication::tr("EXCEPTION"); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 09089fe58..d91d3d69c 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -99,8 +99,9 @@ class DebuggingStateWrapper: public QObject Q_OBJECT Q_PROPERTY(int step READ step) Q_PROPERTY(int curPC READ curPC) - Q_PROPERTY(int gasCost READ gasCost) - Q_PROPERTY(int gas READ gas) + Q_PROPERTY(QString gasCost READ gasCost) + Q_PROPERTY(QString gas READ gas) + Q_PROPERTY(QString gasLeft READ gasLeft) Q_PROPERTY(QString debugStack READ debugStack) Q_PROPERTY(QString debugStorage READ debugStorage) Q_PROPERTY(QString debugMemory READ debugMemory) @@ -113,8 +114,9 @@ public: DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} int step() { return (int)m_state.steps; } int curPC() { return (int)m_state.curPC; } - int gasCost() { return (int)m_state.gasCost; } - int gas() { return (int)m_state.gas; } + QString gasLeft(); + QString gasCost(); + QString gas(); QString debugStack(); QString debugStorage(); QString debugMemory(); diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index ddaa362a6..5cd88d726 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -57,7 +57,6 @@ function endOfDebug() debugStorageTxt.text = ""; debugCallDataTxt.text = ""; debugStackTxt.text = ""; - debugMemoryTxt.text = state.endOfDebug - var gascost = state.gas - state.gasCost; - headerInfoLabel.text = "EXIT | GAS: " + gascost; + debugMemoryTxt.text = state.endOfDebug; + headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft; } From 10763f2407923578f0560d13c06d017dbd4b0de1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 19:16:31 +0100 Subject: [PATCH 17/20] - call initKeyEventManager in a SLOT connected to ressourceLoaded SIGNAL --- mix/AppContext.h | 1 + mix/main.cpp | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mix/AppContext.h b/mix/AppContext.h index 0016ab3be..ce00205d8 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -59,6 +59,7 @@ private: public slots: void quitApplication() { delete Instance; } + void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_obj); Q_UNUSED(_url); initKeyEventManager(); } }; } diff --git a/mix/main.cpp b/mix/main.cpp index 33a139f85..36a742f8f 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,9 +35,7 @@ int main(int _argc, char *_argv[]) QQmlApplicationEngine* engine = new QQmlApplicationEngine(); AppContext::setApplicationContext(engine); QObject::connect(&app, SIGNAL(lastWindowClosed()), AppContext::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff - - engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - - AppContext::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. + QObject::connect(engine, SIGNAL(objectCreated(QObject*, QUrl)), AppContext::getInstance(), SLOT(resourceLoaded(QObject*, QUrl))); + engine->load(QUrl("qrc:/qml/main.qml")); return app.exec(); } From 95217d0584cb76a8a50031ff658dd95f56af0c0e Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 15 Dec 2014 19:40:04 +0100 Subject: [PATCH 18/20] - add parameter QObject* in initKeyEventManager. --- mix/AppContext.cpp | 4 ++-- mix/AppContext.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 5b8b76139..92b3f4c0a 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -52,9 +52,9 @@ dev::eth::Client* AppContext::getEthereumClient() return m_webThree->ethereum(); } -void AppContext::initKeyEventManager() +void AppContext::initKeyEventManager(QObject* _res) { - QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild("mainContent", Qt::FindChildrenRecursively); + QObject* mainContent = _res->findChild("mainContent", Qt::FindChildrenRecursively); if (mainContent) QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); else diff --git a/mix/AppContext.h b/mix/AppContext.h index ce00205d8..baa2905ba 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -47,7 +47,7 @@ public: static void setApplicationContext(QQmlApplicationEngine* _engine); QQmlApplicationEngine* appEngine(); dev::eth::Client* getEthereumClient(); - void initKeyEventManager(); + void initKeyEventManager(QObject* _obj); KeyEventManager* getKeyEventManager(); void displayMessageDialog(QString _title, QString _message); @@ -59,7 +59,7 @@ private: public slots: void quitApplication() { delete Instance; } - void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_obj); Q_UNUSED(_url); initKeyEventManager(); } + void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_url); initKeyEventManager(_obj); } }; } From b2bcf713a60781cdce8a9db19a054d6abd5e0a19 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 16 Dec 2014 13:17:30 +0100 Subject: [PATCH 19/20] - Replace Qt5.3 ModalDialog by custom modal dialog. --- mix/AppContext.cpp | 9 ++++----- mix/Extension.cpp | 5 ++--- mix/qml.qrc | 2 ++ mix/qml/AlertMessageDialog.qml | 27 +++++++++++++++++++++++++++ mix/qml/BasicMessage.qml | 1 + mix/qml/Debugger.qml | 8 -------- mix/qml/ModalDialog.qml | 27 +++++++++++++++++++++++++++ mix/qml/main.qml | 22 +++------------------- 8 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 mix/qml/AlertMessageDialog.qml create mode 100644 mix/qml/ModalDialog.qml diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 92b3f4c0a..89f2849cd 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -74,14 +74,13 @@ void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) void AppContext::displayMessageDialog(QString _title, QString _message) { - QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); - QObject* dialog = component.create(); - dialog->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); - QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("messageDialog", Qt::FindChildrenRecursively); + QObject* dialogWin = m_applicationEngine.get()->rootObjects().at(0)->findChild("alertMessageDialog", Qt::FindChildrenRecursively); + QObject* dialogWinComponent = m_applicationEngine.get()->rootObjects().at(0)->findChild("alertMessageDialogContent", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); - dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml")); dialogWin->setProperty("title", _title); dialogWin->setProperty("width", "250"); dialogWin->setProperty("height", "100"); + dialogWin->findChild("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); QMetaObject::invokeMethod(dialogWin, "open"); } diff --git a/mix/Extension.cpp b/mix/Extension.cpp index f9a8ad94d..e46fc4145 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -65,11 +65,10 @@ void Extension::addContentOn(QObject* _view) Q_UNUSED(_view); if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) { - QQmlComponent component(AppContext::getInstance()->appEngine(), QUrl(contentUrl())); - QObject* dialog = component.create(); QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("dialog", Qt::FindChildrenRecursively); + QObject* dialogWinComponent = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild("modalDialogContent", Qt::FindChildrenRecursively); QMetaObject::invokeMethod(dialogWin, "close"); - dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); + dialogWinComponent->setProperty("source", contentUrl()); dialogWin->setProperty("title", title()); QMetaObject::invokeMethod(dialogWin, "open"); } diff --git a/mix/qml.qrc b/mix/qml.qrc index 2fa92d661..d14aa9974 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -7,5 +7,7 @@ qml/Debugger.qml qml/js/Debugger.js qml/BasicMessage.qml + qml/ModalDialog.qml + qml/AlertMessageDialog.qml diff --git a/mix/qml/AlertMessageDialog.qml b/mix/qml/AlertMessageDialog.qml new file mode 100644 index 000000000..f89ade45f --- /dev/null +++ b/mix/qml/AlertMessageDialog.qml @@ -0,0 +1,27 @@ +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Window +{ + id: alertMessageDialog + title: "" + modality: Qt.WindowModal + height: 150 + width: 200 + visible: false + Loader + { + focus: true + id: alertMessageDialogContent + objectName: "alertMessageDialogContent" + anchors.fill: parent + } + function open() + { + visible = true + } + function close() + { + visible = false + } +} diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 0678c9b54..233717009 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -18,3 +18,4 @@ Rectangle { text: "" } } + diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index e895d1ada..fa3e8aba4 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -21,7 +21,6 @@ Rectangle { font.italic: true id: headerInfoLabel } - } Keys.onPressed: { @@ -138,7 +137,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -149,7 +147,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id:debugStackTxt readOnly: true; @@ -166,7 +163,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -177,7 +173,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id: debugMemoryTxt readOnly: true; @@ -194,7 +189,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top @@ -205,7 +199,6 @@ Rectangle { width: parent.width font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 height: parent.height - 15 id:debugStorageTxt readOnly: true; @@ -222,7 +215,6 @@ Rectangle { horizontalAlignment: "AlignHCenter" font.family: "Verdana" font.pointSize: 8 - font.letterSpacing: 2 width: parent.width height: 15 anchors.top : parent.top diff --git a/mix/qml/ModalDialog.qml b/mix/qml/ModalDialog.qml new file mode 100644 index 000000000..983420926 --- /dev/null +++ b/mix/qml/ModalDialog.qml @@ -0,0 +1,27 @@ +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Window +{ + id: modalDialog + title: "" + modality: Qt.WindowModal + height: 400 + width: 700 + visible: false + Loader + { + focus: true + id: modalDialogContent + objectName: "modalDialogContent" + anchors.fill: parent + } + function open() + { + visible = true + } + function close() + { + visible = false + } +} diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 05b29eb62..52c47e063 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -30,29 +30,13 @@ ApplicationWindow { MainContent { } - Dialog { - x: mainApplication.x + (mainApplication.width - width) / 2 - y: mainApplication.y + (mainApplication.height - height) / 2 + ModalDialog { objectName: "dialog" id: dialog - height: 400 - width: 700 - modality: Qt.WindowModal - contentItem: Rectangle { - objectName: "dialogContent" - } } - Dialog { - x: mainApplication.x + (mainApplication.width - width) / 2 - y: mainApplication.y + (mainApplication.height - height) / 2 - objectName: "messageDialog" + AlertMessageDialog { + objectName: "alertMessageDialog" id: messageDialog - height: 150 - width: 200 - modality: Qt.WindowModal - contentItem: Rectangle { - objectName: "messageContent" - } } } From a22376093a54bc7f478e9458ca4f350cd623c846 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 16 Dec 2014 16:14:13 +0100 Subject: [PATCH 20/20] Prepared State premine. Fixes for Qt 5.2. --- mix/AssemblyDebuggerCtrl.cpp | 3 +-- mix/AssemblyDebuggerModel.cpp | 39 +++++++++++++++++++++-------------- mix/AssemblyDebuggerModel.h | 21 ++++++++++++------- mix/qml/BasicMessage.qml | 6 +++--- mix/qml/Debugger.qml | 6 +++--- mix/qml/MainContent.qml | 4 ++-- mix/qml/main.qml | 2 +- 7 files changed, 48 insertions(+), 33 deletions(-) diff --git a/mix/AssemblyDebuggerCtrl.cpp b/mix/AssemblyDebuggerCtrl.cpp index 678f94d77..e955dfd23 100644 --- a/mix/AssemblyDebuggerCtrl.cpp +++ b/mix/AssemblyDebuggerCtrl.cpp @@ -69,11 +69,10 @@ void AssemblyDebuggerCtrl::keyPressed(int _key) return; } - KeyPair ad = KeyPair::create(); u256 gasPrice = 10000000000000; u256 gas = 1000000; u256 amount = 100; - DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText(), ad); + DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText()); //we need to wrap states in a QObject before sending to QML. QList wStates; diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index 151c14773..1e07760e1 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -18,30 +18,36 @@ */ #include -#include "libethereum/Executive.h" -#include "libethereum/Transaction.h" -#include "libethereum/ExtVM.h" -#include "libevm/VM.h" -#include "libdevcore/Common.h" +#include +#include +#include +#include +#include #include "AppContext.h" #include "TransactionBuilder.h" #include "AssemblyDebuggerModel.h" #include "ConstantCompilationModel.h" #include "DebuggingStateWrapper.h" +using namespace std; using namespace dev; using namespace dev::eth; using namespace dev::mix; -AssemblyDebuggerModel::AssemblyDebuggerModel() +AssemblyDebuggerModel::AssemblyDebuggerModel(): + m_userAccount(KeyPair::create()), + m_baseState(Address(), m_overlayDB, BaseState::Empty) { + m_baseState.addBalance(m_userAccount.address(), 10000000 * ether); m_currentExecution = std::unique_ptr(new Executive(m_executiveState, 0)); } DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) { + // Reset the state back to our clean premine. + m_executiveState = m_baseState; + QList states; - Transaction tr(_rawTransaction); - m_currentExecution->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender()); + m_currentExecution->setup(_rawTransaction); std::vector levels; bytes code; bytesConstRef data; @@ -67,7 +73,9 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); }; + m_currentExecution->go(onOp); + cdebug << states.size(); m_currentExecution->finalize(onOp); DebuggingContent d; @@ -79,11 +87,12 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by return d; } -DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u256 _value, - dev::u256 _gasPrice, - dev::u256 _gas, - QString _code, - KeyPair _key) +DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates( + dev::u256 _value, + dev::u256 _gasPrice, + dev::u256 _gas, + QString _code +) { ConstantCompilationModel compiler; CompilerResult res = compiler.compile(_code); @@ -96,8 +105,8 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::u2 } TransactionBuilder trBuild; - Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, _gas, res.bytes, - m_executiveState.transactionsFrom(dev::toAddress(_key.secret())), _key.secret()); + Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, min(_gas, m_baseState.gasLimitRemaining()), res.bytes, + m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret()); bytes b = tr.rlp(); dev::bytesConstRef bytesRef = &b; return getContractInitiationDebugStates(bytesRef); diff --git a/mix/AssemblyDebuggerModel.h b/mix/AssemblyDebuggerModel.h index 3ed6818bc..b6e0224e8 100644 --- a/mix/AssemblyDebuggerModel.h +++ b/mix/AssemblyDebuggerModel.h @@ -21,9 +21,10 @@ #include #include -#include "libethereum/State.h" -#include "libethereum/Executive.h" -#include "libdevcore/Common.h" +#include +#include +#include +#include #include "DebuggingStateWrapper.h" namespace dev @@ -31,17 +32,23 @@ namespace dev namespace mix { +/** + * @brief Long-life object for managing all executions. + */ class AssemblyDebuggerModel { public: AssemblyDebuggerModel(); - DebuggingContent getContractInitiationDebugStates(dev::u256, dev::u256, dev::u256, QString, KeyPair); - DebuggingContent getContractInitiationDebugStates(dev::bytesConstRef); + DebuggingContent getContractInitiationDebugStates(u256, u256, u256, QString); + DebuggingContent getContractInitiationDebugStates(bytesConstRef); bool compile(QString); private: - std::unique_ptr m_currentExecution; - dev::eth::State m_executiveState; + KeyPair m_userAccount; + OverlayDB m_overlayDB; + eth::State m_baseState; + eth::State m_executiveState; + std::unique_ptr m_currentExecution; }; } diff --git a/mix/qml/BasicMessage.qml b/mix/qml/BasicMessage.qml index 233717009..7127d29ff 100644 --- a/mix/qml/BasicMessage.qml +++ b/mix/qml/BasicMessage.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 Rectangle { diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index fa3e8aba4..18f706970 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import "js/Debugger.js" as Debugger diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 1da48a1c8..6d08f79ec 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 -import QtQuick.Controls 1.2 +import QtQuick.Controls 1.1 import QtQuick.Layouts 1.0 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls.Styles 1.1 import CodeEditorExtensionManager 1.0 Rectangle { diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 52c47e063..42ee3ef97 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 -import QtQuick.Dialogs 1.2 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.0 import CodeEditorExtensionManager 1.0