committed by
yann300
26 changed files with 1353 additions and 33 deletions
@ -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); |
||||
|
}; |
||||
|
} |
@ -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); |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
@ -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; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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() << " " << 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(); |
||||
|
} |
@ -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); |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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()); |
||||
|
} |
||||
|
|
||||
|
|
@ -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); |
||||
|
}; |
||||
|
|
@ -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.
|
||||
|
} |
@ -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; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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: "" |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
Loading…
Reference in new issue