Gav Wood
10 years ago
37 changed files with 1500 additions and 90 deletions
@ -0,0 +1,86 @@ |
|||
/*
|
|||
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 AppContext.cpp
|
|||
* @author Yann yann@ethdev.com |
|||
* @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 AppContext provides reference to: |
|||
* - QQmlApplicationEngine |
|||
* - dev::WebThreeDirect (and dev::eth::Client) |
|||
* - KeyEventManager |
|||
*/ |
|||
|
|||
#include <QDebug> |
|||
#include <QMessageBox> |
|||
#include <QQmlComponent> |
|||
#include <QQmlApplicationEngine> |
|||
#include "libdevcrypto/FileSystem.h" |
|||
#include "KeyEventManager.h" |
|||
#include "AppContext.h" |
|||
using namespace dev; |
|||
using namespace dev::mix; |
|||
using namespace dev::eth; |
|||
|
|||
AppContext* AppContext::Instance = nullptr; |
|||
|
|||
AppContext::AppContext(QQmlApplicationEngine* _engine) |
|||
{ |
|||
m_applicationEngine = std::unique_ptr<QQmlApplicationEngine>(_engine); |
|||
m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager()); |
|||
m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); |
|||
} |
|||
|
|||
QQmlApplicationEngine* AppContext::appEngine() |
|||
{ |
|||
return m_applicationEngine.get(); |
|||
} |
|||
|
|||
dev::eth::Client* AppContext::getEthereumClient() |
|||
{ |
|||
return m_webThree->ethereum(); |
|||
} |
|||
|
|||
void AppContext::initKeyEventManager(QObject* _res) |
|||
{ |
|||
QObject* mainContent = _res->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* AppContext::getKeyEventManager() |
|||
{ |
|||
return m_keyEventManager.get(); |
|||
} |
|||
|
|||
void AppContext::setApplicationContext(QQmlApplicationEngine* _engine) |
|||
{ |
|||
if (Instance == nullptr) |
|||
Instance = new AppContext(_engine); |
|||
} |
|||
|
|||
void AppContext::displayMessageDialog(QString _title, QString _message) |
|||
{ |
|||
QObject* dialogWin = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively); |
|||
QObject* dialogWinComponent = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively); |
|||
QMetaObject::invokeMethod(dialogWin, "close"); |
|||
dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml")); |
|||
dialogWin->setProperty("title", _title); |
|||
dialogWin->setProperty("width", "250"); |
|||
dialogWin->setProperty("height", "100"); |
|||
dialogWin->findChild<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); |
|||
QMetaObject::invokeMethod(dialogWin, "open"); |
|||
} |
@ -0,0 +1,103 @@ |
|||
/*
|
|||
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 <QtConcurrent/QtConcurrent> |
|||
#include <QDebug> |
|||
#include <QQmlContext> |
|||
#include <QModelIndex> |
|||
#include "libethereum/Transaction.h" |
|||
#include "AssemblyDebuggerModel.h" |
|||
#include "AssemblyDebuggerCtrl.h" |
|||
#include "TransactionBuilder.h" |
|||
#include "KeyEventManager.h" |
|||
#include "AppContext.h" |
|||
#include "DebuggingStateWrapper.h" |
|||
using namespace dev::mix; |
|||
|
|||
AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog) |
|||
{ |
|||
qRegisterMetaType<AssemblyDebuggerData>(); |
|||
qRegisterMetaType<DebuggingStatusResult>(); |
|||
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)), |
|||
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection); |
|||
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 QApplication::tr("debugger"); |
|||
} |
|||
|
|||
void AssemblyDebuggerCtrl::start() const |
|||
{ |
|||
//start to listen on F5
|
|||
m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); |
|||
} |
|||
|
|||
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())) |
|||
{ |
|||
emit dataAvailable(false, DebuggingStatusResult::Compilationfailed); |
|||
return; |
|||
} |
|||
|
|||
u256 gasPrice = 10000000000000; |
|||
u256 gas = 1000000; |
|||
u256 amount = 100; |
|||
DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText()); |
|||
|
|||
//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(), this); |
|||
s->setState(debuggingContent.states.at(i)); |
|||
wStates.append(s); |
|||
} |
|||
AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); |
|||
emit dataAvailable(true, DebuggingStatusResult::Ok, wStates, code); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates, AssemblyDebuggerData _code) |
|||
{ |
|||
Q_UNUSED(reason); |
|||
if (success) |
|||
{ |
|||
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 |
|||
m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed")); |
|||
} |
@ -0,0 +1,70 @@ |
|||
/*
|
|||
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" |
|||
#include "AppContext.h" |
|||
|
|||
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>; |
|||
enum DebuggingStatusResult |
|||
{ |
|||
Ok, |
|||
Compilationfailed |
|||
}; |
|||
|
|||
Q_DECLARE_METATYPE(AssemblyDebuggerData) |
|||
Q_DECLARE_METATYPE(DebuggingStatusResult) |
|||
|
|||
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 slots: |
|||
void keyPressed(int); |
|||
void updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData()); |
|||
|
|||
signals: |
|||
void dataAvailable(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData()); |
|||
|
|||
}; |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,120 @@ |
|||
/*
|
|||
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 <QApplication> |
|||
#include <libdevcore/Common.h> |
|||
#include <libevm/VM.h> |
|||
#include <libethereum/Executive.h> |
|||
#include <libethereum/Transaction.h> |
|||
#include <libethereum/ExtVM.h> |
|||
#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(): |
|||
m_userAccount(KeyPair::create()), |
|||
m_baseState(Address(), m_overlayDB, BaseState::Empty) |
|||
{ |
|||
m_baseState.addBalance(m_userAccount.address(), 10000000 * ether); |
|||
m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState, 0)); |
|||
} |
|||
|
|||
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) |
|||
{ |
|||
// Reset the state back to our clean premine.
|
|||
m_executiveState = m_baseState; |
|||
|
|||
QList<DebuggingState> states; |
|||
m_currentExecution->setup(_rawTransaction); |
|||
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->go(onOp); |
|||
cdebug << states.size(); |
|||
m_currentExecution->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 |
|||
) |
|||
{ |
|||
ConstantCompilationModel compiler; |
|||
CompilerResult res = compiler.compile(_code); |
|||
if (!res.success) |
|||
{ |
|||
DebuggingContent r; |
|||
r.contentAvailable = false; |
|||
r.message = QApplication::tr("compilation failed"); |
|||
return r; |
|||
} |
|||
|
|||
TransactionBuilder trBuild; |
|||
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); |
|||
} |
|||
|
|||
bool AssemblyDebuggerModel::compile(QString _code) |
|||
{ |
|||
ConstantCompilationModel compiler; |
|||
CompilerResult res = compiler.compile(_code); |
|||
return res.success; |
|||
} |
@ -0,0 +1,56 @@ |
|||
/*
|
|||
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 <libdevcore/Common.h> |
|||
#include <libdevcrypto/Common.h> |
|||
#include <libethereum/State.h> |
|||
#include <libethereum/Executive.h> |
|||
#include "DebuggingStateWrapper.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace mix |
|||
{ |
|||
|
|||
/**
|
|||
* @brief Long-life object for managing all executions. |
|||
*/ |
|||
class AssemblyDebuggerModel |
|||
{ |
|||
public: |
|||
AssemblyDebuggerModel(); |
|||
DebuggingContent getContractInitiationDebugStates(u256, u256, u256, QString); |
|||
DebuggingContent getContractInitiationDebugStates(bytesConstRef); |
|||
bool compile(QString); |
|||
|
|||
private: |
|||
KeyPair m_userAccount; |
|||
OverlayDB m_overlayDB; |
|||
eth::State m_baseState; |
|||
eth::State m_executiveState; |
|||
std::unique_ptr<eth::Executive> m_currentExecution; |
|||
}; |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,158 @@ |
|||
/*
|
|||
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 DebuggingStateWrapper.cpp
|
|||
* @author Yann yann@ethdev.com |
|||
* @date 2014 |
|||
* Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). |
|||
*/ |
|||
|
|||
#include <QApplication> |
|||
#include <QDebug> |
|||
#include "libevmcore/Instruction.h" |
|||
#include "libdevcore/CommonJS.h" |
|||
#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, QObject* _objUsedAsParent) |
|||
{ |
|||
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 << 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) |
|||
{ |
|||
unsigned bc = getPushNumber((Instruction)b); |
|||
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); |
|||
i += bc; |
|||
} |
|||
HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent); |
|||
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, _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; |
|||
for (auto i: m_state.stack) |
|||
stack.prepend(QString::fromStdString(prettyU256(i)) + "\n"); |
|||
|
|||
return stack; |
|||
} |
|||
|
|||
QString DebuggingStateWrapper::debugStorage() |
|||
{ |
|||
std::stringstream s; |
|||
for (auto const& i: m_state.storage) |
|||
s << "@" << prettyU256(i.first) << " " << prettyU256(i.second); |
|||
|
|||
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) |
|||
{ |
|||
std::ostringstream out; |
|||
out << m_state.cur.abridged(); |
|||
if (i) |
|||
out << " " << instructionInfo(m_state.inst).name << " @0x" << std::hex << m_state.curPC; |
|||
levelsStr.append(QString::fromStdString(out.str())); |
|||
} |
|||
return levelsStr; |
|||
} |
|||
|
|||
QString DebuggingStateWrapper::headerInfo() |
|||
{ |
|||
std::ostringstream ss; |
|||
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 QApplication::tr("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 QApplication::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); |
|||
} |
|||
else if (m_state.inst == Instruction::STOP) |
|||
return QApplication::tr("STOP"); |
|||
else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) |
|||
return QApplication::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); |
|||
else |
|||
return QApplication::tr("EXCEPTION"); |
|||
} |
@ -0,0 +1,139 @@ |
|||
/*
|
|||
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 DebuggingStateWrapper.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; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief 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, QObject* _parent): QObject(_parent), m_line(_line), m_processIndex(_processIndex) {} |
|||
QString line() { return m_line; } |
|||
int processIndex() { return m_processIndex; } |
|||
|
|||
private: |
|||
QString m_line; |
|||
int m_processIndex; |
|||
}; |
|||
|
|||
|
|||
/**
|
|||
* @brief Publish QMap type to QML. |
|||
*/ |
|||
class QQMLMap: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
QQMLMap(QMap<int, int> _map, QObject* _parent): QObject(_parent), m_map(_map) { } |
|||
Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } |
|||
|
|||
private: |
|||
QMap<int, int> m_map; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Wrap DebuggingState in QObject |
|||
*/ |
|||
class DebuggingStateWrapper: public QObject |
|||
{ |
|||
Q_OBJECT |
|||
Q_PROPERTY(int step READ step) |
|||
Q_PROPERTY(int curPC READ curPC) |
|||
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) |
|||
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, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {} |
|||
int step() { return (int)m_state.steps; } |
|||
int curPC() { return (int)m_state.curPC; } |
|||
QString gasLeft(); |
|||
QString gasCost(); |
|||
QString 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, QObject* _objUsedAsParent); |
|||
|
|||
private: |
|||
DebuggingState m_state; |
|||
bytes m_code; |
|||
bytes m_data; |
|||
}; |
|||
|
|||
} |
|||
|
|||
} |
@ -1,36 +1,41 @@ |
|||
/*
|
|||
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 ApplicationCtx.cpp
|
|||
/** @file KeyEventManager.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. |
|||
* In the future this class can be extended to add more variable related to the context of the application. |
|||
* 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 <QQmlApplicationEngine> |
|||
#include "ApplicationCtx.h" |
|||
using namespace dev::mix; |
|||
#include <QDebug> |
|||
#include <QKeySequence> |
|||
#include "KeyEventManager.h" |
|||
|
|||
ApplicationCtx* ApplicationCtx::Instance = nullptr; |
|||
void KeyEventManager::registerEvent(const QObject* _receiver, const char* _slot) |
|||
{ |
|||
QObject::connect(this, SIGNAL(onKeyPressed(int)), _receiver, _slot); |
|||
} |
|||
|
|||
QQmlApplicationEngine* ApplicationCtx::appEngine() |
|||
void KeyEventManager::unRegisterEvent(QObject* _receiver) |
|||
{ |
|||
return m_applicationEngine; |
|||
QObject::disconnect(_receiver); |
|||
} |
|||
|
|||
void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) |
|||
void KeyEventManager::keyPressed(QVariant _event) |
|||
{ |
|||
if (Instance == nullptr) |
|||
Instance = new ApplicationCtx(_engine); |
|||
emit onKeyPressed(_event.toInt()); |
|||
} |
@ -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 slots: |
|||
void keyPressed(QVariant _event); |
|||
}; |
|||
|
@ -0,0 +1,40 @@ |
|||
/*
|
|||
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/CommonJS.h" |
|||
#include "libdevcore/Common.h" |
|||
#include "AppContext.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, dev::fromString(_address.toStdString()), _data, _nonce, _secret); |
|||
} |
|||
|
@ -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 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; |
|||
}; |
|||
|
|||
} |
|||
|
|||
} |
@ -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 |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
import QtQuick 2.2 |
|||
import QtQuick.Controls.Styles 1.1 |
|||
import QtQuick.Controls 1.1 |
|||
import QtQuick.Dialogs 1.1 |
|||
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: "" |
|||
} |
|||
} |
|||
|
@ -0,0 +1,232 @@ |
|||
import QtQuick 2.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 |
|||
|
|||
Rectangle { |
|||
anchors.fill: parent; |
|||
color: "lightgrey" |
|||
Rectangle { |
|||
color: "transparent" |
|||
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 { |
|||
color: "transparent" |
|||
id: stateListContainer |
|||
focus: true |
|||
anchors.topMargin: 10 |
|||
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.60 |
|||
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 { |
|||
id: callStackPanel |
|||
anchors.top: statesList.bottom |
|||
height: parent.height * 0.35 |
|||
width: parent.width |
|||
anchors.topMargin: 15 |
|||
color: "transparent" |
|||
Label { |
|||
id: callStackLabel |
|||
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 { |
|||
color: "transparent" |
|||
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 |
|||
color: "transparent" |
|||
Label { |
|||
horizontalAlignment: "AlignHCenter" |
|||
font.family: "Verdana" |
|||
font.pointSize: 8 |
|||
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 |
|||
height: parent.height - 15 |
|||
id:debugStackTxt |
|||
readOnly: true; |
|||
} |
|||
} |
|||
|
|||
Rectangle { |
|||
id: debugMemory |
|||
anchors.top: debugStack.bottom |
|||
width: parent.width |
|||
height: parent.height * 0.25 |
|||
color: "transparent" |
|||
Label { |
|||
horizontalAlignment: "AlignHCenter" |
|||
font.family: "Verdana" |
|||
font.pointSize: 8 |
|||
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 |
|||
height: parent.height - 15 |
|||
id: debugMemoryTxt |
|||
readOnly: true; |
|||
} |
|||
} |
|||
|
|||
Rectangle { |
|||
id: debugStorage |
|||
anchors.top: debugMemory.bottom |
|||
width: parent.width |
|||
height: parent.height * 0.25 |
|||
color: "transparent" |
|||
Label { |
|||
horizontalAlignment: "AlignHCenter" |
|||
font.family: "Verdana" |
|||
font.pointSize: 8 |
|||
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 |
|||
height: parent.height - 15 |
|||
id:debugStorageTxt |
|||
readOnly: true; |
|||
} |
|||
} |
|||
|
|||
Rectangle { |
|||
id: debugCallData |
|||
anchors.top: debugStorage.bottom |
|||
width: parent.width |
|||
height: parent.height * 0.25 |
|||
color: "transparent" |
|||
Label { |
|||
horizontalAlignment: "AlignHCenter" |
|||
font.family: "Verdana" |
|||
font.pointSize: 8 |
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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 |
|||
} |
|||
} |
@ -0,0 +1,62 @@ |
|||
//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; |
|||
headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft; |
|||
} |
Loading…
Reference in new issue