Gav Wood
10 years ago
35 changed files with 1458 additions and 93 deletions
@ -0,0 +1,87 @@ |
|||||
|
/*
|
||||
|
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* 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* 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) |
||||
|
{ |
||||
|
QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml")); |
||||
|
QObject* dialog = component.create(); |
||||
|
dialog->findChild<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); |
||||
|
QObject* dialogWin = AppContext::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"); |
||||
|
} |
@ -0,0 +1,104 @@ |
|||||
|
/*
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
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(), 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,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 <QApplication> |
||||
|
#include "libethereum/Executive.h" |
||||
|
#include "libethereum/Transaction.h" |
||||
|
#include "libethereum/ExtVM.h" |
||||
|
#include "libevm/VM.h" |
||||
|
#include "libdevcore/Common.h" |
||||
|
#include "AppContext.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, 0)); |
||||
|
} |
||||
|
|
||||
|
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) |
||||
|
{ |
||||
|
QList<DebuggingState> states; |
||||
|
Transaction tr(_rawTransaction); |
||||
|
m_currentExecution->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->go(onOp); |
||||
|
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, |
||||
|
KeyPair _key) |
||||
|
{ |
||||
|
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, _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; |
||||
|
} |
@ -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); |
||||
|
|
||||
|
private: |
||||
|
std::unique_ptr<dev::eth::Executive> m_currentExecution; |
||||
|
dev::eth::State m_executiveState; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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. |
This file is part of cpp-ethereum. |
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
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 |
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
(at your option) any later version. |
||||
|
|
||||
cpp-ethereum is distributed in the hope that it will be useful, |
cpp-ethereum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
GNU General Public License for more details. |
||||
|
|
||||
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
*/ |
||||
/** @file ApplicationCtx.cpp
|
/** @file KeyEventManager.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. |
* Used as an event handler for all classes which need keyboard interactions. |
||||
* In the future this class can be extended to add more variable related to the context of the application. |
* Can be improve by adding the possibility to register to a specific key. |
||||
*/ |
*/ |
||||
|
|
||||
#include <QQmlApplicationEngine> |
#include <QDebug> |
||||
#include "ApplicationCtx.h" |
#include <QKeySequence> |
||||
using namespace dev::mix; |
#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) |
emit onKeyPressed(_event.toInt()); |
||||
Instance = new ApplicationCtx(_engine); |
|
||||
} |
} |
@ -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,20 @@ |
|||||
|
import QtQuick 2.2 |
||||
|
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: "" |
||||
|
} |
||||
|
} |
@ -0,0 +1,240 @@ |
|||||
|
import QtQuick 2.2 |
||||
|
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; |
||||
|
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 |
||||
|
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 |
||||
|
color: "transparent" |
||||
|
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 |
||||
|
color: "transparent" |
||||
|
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 |
||||
|
color: "transparent" |
||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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