Browse Source

mix IDE M1 first commit

cl-refactor
yann300 10 years ago
committed by yann300
parent
commit
f990a1ac63
  1. 62
      mix/ApplicationCtx.cpp
  2. 19
      mix/ApplicationCtx.h
  3. 84
      mix/AssemblyDebuggerCtrl.cpp
  4. 55
      mix/AssemblyDebuggerCtrl.h
  5. 111
      mix/AssemblyDebuggerModel.cpp
  6. 49
      mix/AssemblyDebuggerModel.h
  7. 22
      mix/CodeEditorExtensionManager.cpp
  8. 3
      mix/CodeEditorExtensionManager.h
  9. 4
      mix/ConstantCompilationCtrl.cpp
  10. 1
      mix/ConstantCompilationModel.cpp
  11. 2
      mix/ConstantCompilationModel.h
  12. 189
      mix/DebuggingStateWrapper.cpp
  13. 133
      mix/DebuggingStateWrapper.h
  14. 23
      mix/Extension.cpp
  15. 14
      mix/Extension.h
  16. 43
      mix/KeyEventManager.cpp
  17. 42
      mix/KeyEventManager.h
  18. 92
      mix/TransactionBuilder.cpp
  19. 48
      mix/TransactionBuilder.h
  20. 3
      mix/main.cpp
  21. 3
      mix/qml.qrc
  22. 20
      mix/qml/BasicMessage.qml
  23. 231
      mix/qml/Debugger.qml
  24. 14
      mix/qml/MainContent.qml
  25. 63
      mix/qml/js/Debugger.js
  26. 38
      mix/qml/main.qml

62
mix/ApplicationCtx.cpp

@ -14,23 +14,83 @@
/** @file ApplicationCtx.cpp /** @file ApplicationCtx.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @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. * 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 <QDebug>
#include <QMessageBox>
#include <QQmlComponent>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "libdevcrypto/FileSystem.h"
#include "KeyEventManager.h"
#include "ApplicationCtx.h" #include "ApplicationCtx.h"
using namespace dev;
using namespace dev::mix; using namespace dev::mix;
using namespace dev::eth;
ApplicationCtx* ApplicationCtx::Instance = nullptr; ApplicationCtx* ApplicationCtx::Instance = nullptr;
ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine)
{
m_applicationEngine = _engine;
m_keyEventManager = std::unique_ptr<KeyEventManager>();
m_webThree = std::unique_ptr<dev::WebThreeDirect>();
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() QQmlApplicationEngine* ApplicationCtx::appEngine()
{ {
return m_applicationEngine; return m_applicationEngine;
} }
dev::eth::Client* ApplicationCtx::getEthereumClient()
{
return m_webThree.get()->ethereum();
}
void ApplicationCtx::initKeyEventManager()
{
QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("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) void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine)
{ {
if (Instance == nullptr) if (Instance == nullptr)
Instance = new ApplicationCtx(_engine); 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<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message);
QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("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");
}

19
mix/ApplicationCtx.h

@ -16,14 +16,19 @@
*/ */
/** @file ApplicationCtx.h /** @file ApplicationCtx.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly.
* Provide 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. * 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 #pragma once
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "libwebthree/WebThree.h"
#include "KeyEventManager.h"
namespace dev namespace dev
{ {
@ -36,15 +41,21 @@ class ApplicationCtx: public QObject
Q_OBJECT Q_OBJECT
public: public:
ApplicationCtx(QQmlApplicationEngine* _engine) { m_applicationEngine = _engine; } ApplicationCtx(QQmlApplicationEngine* _engine);
~ApplicationCtx() { delete m_applicationEngine; } ~ApplicationCtx();
static ApplicationCtx* getInstance() { return Instance; } static ApplicationCtx* getInstance() { return Instance; }
static void setApplicationContext(QQmlApplicationEngine* _engine); static void setApplicationContext(QQmlApplicationEngine* _engine);
QQmlApplicationEngine* appEngine(); QQmlApplicationEngine* appEngine();
dev::eth::Client* getEthereumClient();
void initKeyEventManager();
KeyEventManager* getKeyEventManager();
void displayMessageDialog(QString _title, QString _message);
private: private:
static ApplicationCtx* Instance; static ApplicationCtx* Instance;
QQmlApplicationEngine* m_applicationEngine; QQmlApplicationEngine* m_applicationEngine;
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<KeyEventManager> m_keyEventManager;
public slots: public slots:
void quitApplication() { delete Instance; } void quitApplication() { delete Instance; }

84
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 <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* display opcode debugging.
*/
#include <QDebug>
#include <QQmlContext>
#include <QModelIndex>
#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<AssemblyDebuggerModel>(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<QObject*> 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<QList<QObject*>, 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);
};
}

55
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 <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QKeySequence>
#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<AssemblyDebuggerModel> m_modelDebugger;
QTextDocument* m_doc;
public Q_SLOTS:
void keyPressed(int);
};
}
}

111
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 <http://www.gnu.org/licenses/>.
*/
/** @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<Executive>(new Executive(m_executiveState));
}
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction)
{
QList<DebuggingState> states;
Transaction tr(_rawTransaction);
m_currentExecution.get()->create(tr.sender(), tr.value(), tr.gasPrice(), tr.gas(), &tr.data(), tr.sender());
std::vector<DebuggingState const*> 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;
}

49
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 <http://www.gnu.org/licenses/>.
*/
/** @file AssemblyDebuggerModel.h
* @author Yann yann@ethdev.com
* @date 2014
* serves as a model to debug contract assembly code.
*/
#pragma once
#include <QObject>
#include <QList>
#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<dev::eth::Executive> m_currentExecution;
dev::eth::State m_executiveState;
};
}
}

22
mix/CodeEditorExtensionManager.cpp

@ -27,6 +27,7 @@
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationCtrl.h"
#include "AssemblyDebuggerCtrl.h"
#include "features.h" #include "features.h"
#include "ApplicationCtx.h" #include "ApplicationCtx.h"
#include "CodeEditorExtensionManager.h" #include "CodeEditorExtensionManager.h"
@ -59,22 +60,29 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtensions()
{ {
//only one for now initExtension(std::make_shared<ConstantCompilationCtrl>(m_doc));
std::shared_ptr<ConstantCompilationCtrl> constantCompilation = std::make_shared<ConstantCompilationCtrl>(m_doc); initExtension(std::make_shared<AssemblyDebuggerCtrl>(m_doc));
if (constantCompilation.get()->contentUrl() != "") }
void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> ext)
{
if (!ext.get()->contentUrl().isEmpty())
{ {
try try
{ {
constantCompilation.get()->addContentOn(m_tabView); if (ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab)
{
ext.get()->addTabOn(m_tabView);
}
} }
catch (...) catch (...)
{ {
qDebug() << "Exception when adding content into view."; qDebug() << "Exception when adding tab into view.";
return; return;
} }
} }
constantCompilation.get()->start(); ext.get()->start();
m_features.append(constantCompilation); m_features.append(ext);
} }
void CodeEditorExtensionManager::setEditor(QQuickItem* _editor) void CodeEditorExtensionManager::setEditor(QQuickItem* _editor)

3
mix/CodeEditorExtensionManager.h

@ -45,12 +45,13 @@ public:
CodeEditorExtensionManager() {} CodeEditorExtensionManager() {}
~CodeEditorExtensionManager(); ~CodeEditorExtensionManager();
void initExtensions(); void initExtensions();
void initExtension(std::shared_ptr<Extension>);
void setEditor(QQuickItem*); void setEditor(QQuickItem*);
void setTabView(QQuickItem*); void setTabView(QQuickItem*);
private: private:
QQuickItem* m_editor; QQuickItem* m_editor;
QVector<std::shared_ptr<ConstantCompilationCtrl>> m_features; QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView; QQuickItem* m_tabView;
QTextDocument* m_doc; QTextDocument* m_doc;
void loadEditor(QQuickItem*); void loadEditor(QQuickItem*);

4
mix/ConstantCompilationCtrl.cpp

@ -30,7 +30,7 @@
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
using namespace dev::mix; using namespace dev::mix;
ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc) ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab)
{ {
m_editor = _doc; m_editor = _doc;
m_compilationModel = new ConstantCompilationModel(); m_compilationModel = new ConstantCompilationModel();
@ -64,7 +64,7 @@ void ConstantCompilationCtrl::compile()
resetOutPut(); resetOutPut();
return; return;
} }
CompilerResult res = m_compilationModel->compile(m_editor->toPlainText()); CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " "));
writeOutPut(res); writeOutPut(res);
} }

1
mix/ConstantCompilationModel.cpp

@ -42,6 +42,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code)
res.success = true; res.success = true;
res.comment = "ok"; res.comment = "ok";
res.hexCode = QString::fromStdString(dev::eth::disassemble(m_data)); res.hexCode = QString::fromStdString(dev::eth::disassemble(m_data));
res.bytes = m_data;
} }
catch (dev::Exception const& _exception) catch (dev::Exception const& _exception)
{ {

2
mix/ConstantCompilationModel.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <libevm/VM.h>
#include <QObject> #include <QObject>
namespace dev namespace dev
@ -34,6 +35,7 @@ struct CompilerResult
{ {
QString hexCode; QString hexCode;
QString comment; QString comment;
dev::bytes bytes;
bool success; bool success;
}; };

189
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 <http://www.gnu.org/licenses/>.
*/
/** @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 <QDebug>
#include <QString>
#include <QTextStream>
#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<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& code)
{
QList<QObject*> codeStr;
QMap<int, int> 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() << "&nbsp;&nbsp;&nbsp;&nbsp;" << 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();
}

133
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 <http://www.gnu.org/licenses/>.
*/
/** @file DebuggingState.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QStringList>
#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<dev::u256, dev::u256> storage;
std::vector<DebuggingState const*> levels;
};
struct DebuggingContent
{
QList<DebuggingState> 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<int, int> _map) : m_map(_map) { }
Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); }
private:
QMap<int, int> 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<QList<QObject*>, 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);
};
}
}

23
mix/Extension.cpp

@ -25,7 +25,7 @@
using namespace dev; using namespace dev;
using namespace dev::mix; using namespace dev::mix;
void Extension::addContentOn(QObject* _tabView) void Extension::addTabOn(QObject* _view)
{ {
if (contentUrl() == "") if (contentUrl() == "")
return; return;
@ -33,12 +33,29 @@ void Extension::addContentOn(QObject* _tabView)
QVariant returnValue; QVariant returnValue;
QQmlComponent* component = new QQmlComponent( QQmlComponent* component = new QQmlComponent(
ApplicationCtx::getInstance()->appEngine(), ApplicationCtx::getInstance()->appEngine(),
QUrl(this->contentUrl()), _tabView); QUrl(contentUrl()), _view);
QMetaObject::invokeMethod(_tabView, "addTab", QMetaObject::invokeMethod(_view, "addTab",
Q_RETURN_ARG(QVariant, returnValue), Q_RETURN_ARG(QVariant, returnValue),
Q_ARG(QVariant, this->title()), Q_ARG(QVariant, this->title()),
Q_ARG(QVariant, QVariant::fromValue(component))); Q_ARG(QVariant, QVariant::fromValue(component)));
m_view = qvariant_cast<QObject*>(returnValue); m_view = qvariant_cast<QObject*>(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<QObject*>("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.
}

14
mix/Extension.h

@ -28,19 +28,31 @@ namespace dev
namespace mix namespace mix
{ {
enum ExtensionDisplayBehavior
{
Tab,
ModalDialog
};
class Extension: public QObject class Extension: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Extension() {} Extension() {}
Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; }
virtual QString contentUrl() const { return ""; } virtual QString contentUrl() const { return ""; }
virtual QString title() const { return ""; } virtual QString title() const { return ""; }
virtual void start() const {} 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: protected:
QObject* m_view; QObject* m_view;
ExtensionDisplayBehavior m_displayBehavior;
}; };
} }

43
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 <http://www.gnu.org/licenses/>.
*/
/** @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 <QDebug>
#include <QKeySequence>
#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());
}

42
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 <http://www.gnu.org/licenses/>.
*/
/** @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 <QObject>
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);
};

92
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 <http://www.gnu.org/licenses/>.
*/
/** @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<uint8_t> 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.
}

48
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 <http://www.gnu.org/licenses/>.
*/
/** @file TransactionBuilder.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QString>
#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;
};
}
}

3
mix/main.cpp

@ -35,6 +35,9 @@ int main(int _argc, char *_argv[])
QQmlApplicationEngine* engine = new QQmlApplicationEngine(); QQmlApplicationEngine* engine = new QQmlApplicationEngine();
ApplicationCtx::setApplicationContext(engine); ApplicationCtx::setApplicationContext(engine);
QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff
engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); 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(); return app.exec();
} }

3
mix/qml.qrc

@ -4,5 +4,8 @@
<file>qml/main.qml</file> <file>qml/main.qml</file>
<file>qml/MainContent.qml</file> <file>qml/MainContent.qml</file>
<file>qml/TabStyle.qml</file> <file>qml/TabStyle.qml</file>
<file>qml/Debugger.qml</file>
<file>qml/js/Debugger.js</file>
<file>qml/BasicMessage.qml</file>
</qresource> </qresource>
</RCC> </RCC>

20
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: ""
}
}

231
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;
}
}
}
}

14
mix/qml/MainContent.qml

@ -1,10 +1,18 @@
import QtQuick 2.2 import QtQuick 2.3
import QtQuick.Controls 1.1 import QtQuick.Controls 1.2
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1 import QtQuick.Controls.Styles 1.2
import CodeEditorExtensionManager 1.0 import CodeEditorExtensionManager 1.0
Rectangle { Rectangle {
objectName: "mainContent"
signal keyPressed(variant event)
focus: true
Keys.enabled: true
Keys.onPressed:
{
root.keyPressed(event.key);
}
anchors.fill: parent anchors.fill: parent
height: parent.height height: parent.height
width: parent.width; width: parent.width;

63
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;
}

38
mix/qml/main.qml

@ -1,15 +1,22 @@
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Controls 1.1 import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 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 import CodeEditorExtensionManager 1.0
ApplicationWindow { ApplicationWindow {
id: mainApplication
visible: true visible: true
width: 1000 x: Screen.width / 2 - width / 2
height: 480 y: Screen.height / 2 - height / 2
width: 1200
height: 600
minimumWidth: 400 minimumWidth: 400
minimumHeight: 300 minimumHeight: 300
title: qsTr("mix") title: qsTr("mix")
menuBar: MenuBar { menuBar: MenuBar {
Menu { Menu {
title: qsTr("File") 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"
}
}
} }

Loading…
Cancel
Save