diff --git a/mix/AssemblyDebuggerControl.cpp b/mix/AssemblyDebuggerControl.cpp index f52245450..e065513a8 100644 --- a/mix/AssemblyDebuggerControl.cpp +++ b/mix/AssemblyDebuggerControl.cpp @@ -29,7 +29,6 @@ using namespace dev::mix; AssemblyDebuggerControl::AssemblyDebuggerControl(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightView) { - connect(_context->clientModel(), &ClientModel::showDebuggerWindow, this, &AssemblyDebuggerControl::showDebugger, Qt::QueuedConnection); } QString AssemblyDebuggerControl::contentUrl() const @@ -45,9 +44,3 @@ QString AssemblyDebuggerControl::title() const void AssemblyDebuggerControl::start() const { } - -void AssemblyDebuggerControl::showDebugger() -{ - QObject* debugPanel = m_view->findChild("debugPanel", Qt::FindChildrenRecursively); - QMetaObject::invokeMethod(debugPanel, "update", Q_ARG(QVariant, true)); -} diff --git a/mix/AssemblyDebuggerControl.h b/mix/AssemblyDebuggerControl.h index 1240b3807..701cbc5fd 100644 --- a/mix/AssemblyDebuggerControl.h +++ b/mix/AssemblyDebuggerControl.h @@ -42,10 +42,6 @@ public: void start() const override; QString title() const override; QString contentUrl() const override; - -private slots: - /// Update UI with machine states result. Displayed in the right side tab. - void showDebugger(); }; } diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 251447c79..914edf52d 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -72,7 +72,10 @@ ClientModel::ClientModel(AppContext* _context): qRegisterMetaType>("QList"); qRegisterMetaType>("QList"); qRegisterMetaType("QVariableDeclaration*"); - qRegisterMetaType("AssemblyDebuggerData"); + qRegisterMetaType("QMachineState"); + qRegisterMetaType("QInstruction"); + qRegisterMetaType("QCode"); + qRegisterMetaType("QCallData"); qRegisterMetaType("TransactionLogEntry"); connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); @@ -251,24 +254,27 @@ void ClientModel::showDebugger() void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) { //we need to wrap states in a QObject before sending to QML. - QList wStates; - for (unsigned i = 0; i < _t.machineStates.size(); i++) - { - QPointer s(new DebuggingStateWrapper(_t.executionCode, _t.executionData.toBytes())); - s->setState(_t.machineStates[i]); - wStates.append(s); - } + QDebugData* debugData = new QDebugData(); + QQmlEngine::setObjectOwnership(debugData, QQmlEngine::JavaScriptOwnership); + QList codes; + for (bytes const& code: _t.executionCode) + codes.push_back(QMachineState::getHumanReadableCode(debugData, code)); + + QList data; + for (bytes const& d: _t.transactionData) + data.push_back(QMachineState::getDebugCallData(debugData, d)); + + QVariantList states; + for (MachineState const& s: _t.machineStates) + states.append(QVariant::fromValue(new QMachineState(debugData, s, codes[s.codeIndex], data[s.dataIndex]))); + + debugData->setStates(std::move(states)); - QList returnParameters; + //QList returnParameters; //returnParameters = encoder.decode(f->returnParameters(), debuggingContent.returnValue); //collect states for last transaction - AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(_t.executionCode); - m_context->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); - m_context->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); - m_context->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); - m_context->appEngine()->rootContext()->setContextProperty("contractCallReturnParameters", QVariant::fromValue(new QVariableDefinitionList(returnParameters))); - showDebuggerWindow(); + debugDataReady(debugData); } @@ -339,9 +345,9 @@ void ClientModel::onNewTransaction() else { //call - if (tr.transactionData.size() >= 4) + if (tr.transactionData.size() > 0 && tr.transactionData.front().size() >= 4) { - functionHash = FixedHash<4>(tr.transactionData.data(), FixedHash<4>::ConstructFromPointer); + functionHash = FixedHash<4>(tr.transactionData.front().data(), FixedHash<4>::ConstructFromPointer); function = QString::fromStdString(toJS(functionHash)); call = true; } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 016673ba6..729d6acf6 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -25,14 +25,9 @@ #include #include -#include "DebuggingStateWrapper.h" +#include #include "MixClient.h" -using AssemblyDebuggerData = std::tuple, dev::mix::QQMLMap*>; - -Q_DECLARE_METATYPE(AssemblyDebuggerData) -Q_DECLARE_METATYPE(dev::mix::ExecutionResult) - namespace dev { namespace mix @@ -42,6 +37,7 @@ class AppContext; class Web3Server; class RpcConnector; class QEther; +class QDebugData; /// Backend transaction config class struct TransactionSettings @@ -156,7 +152,7 @@ signals: /// Execution state changed void runStateChanged(); /// Show debugger window request - void showDebuggerWindow(); + void debugDataReady(QObject* _debugData); /// ethereum.js RPC response ready /// @param _message RPC response in Json format void apiResponse(QString const& _message); diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 39edd6d6f..b811bc172 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -133,7 +133,7 @@ void CodeModel::runCompilationJob(int _jobId, QString const& _code) if (_jobId != m_backgroundJobId) return; //obsolete job - solidity::CompilerStack cs; + solidity::CompilerStack cs(true); std::unique_ptr result; std::string source = _code.toStdString(); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 1eacac120..c99ce9681 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,10 +36,9 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; -std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code) +QCode* QMachineState::getHumanReadableCode(QObject* _owner, const bytes& _code) { - QList codeStr; - QMap codeMapping; + QVariantList codeStr; for (unsigned i = 0; i <= _code.size(); ++i) { byte b = i < _code.size() ? _code[i] : 0; @@ -47,7 +47,6 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod 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) { @@ -55,8 +54,7 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); i += bc; } - QPointer humanCode(new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line)); - codeStr.append(humanCode); + codeStr.append(QVariant::fromValue(new QInstruction(_owner, QString::fromStdString(out.str()) + " " + s, line))); } catch (...) { @@ -65,25 +63,25 @@ std::tuple, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod break; // probably hit data segment } } - return std::make_tuple(codeStr, QPointer(new QQMLMap(codeMapping))); + return new QCode(_owner, std::move(codeStr)); } -QBigInt* DebuggingStateWrapper::gasCost() +QBigInt* QMachineState::gasCost() { return new QBigInt(m_state.gasCost); } -QBigInt* DebuggingStateWrapper::gas() +QBigInt* QMachineState::gas() { return new QBigInt(m_state.gas); } -QBigInt* DebuggingStateWrapper::newMemSize() +QBigInt* QMachineState::newMemSize() { return new QBigInt(m_state.newMemSize); } -QStringList DebuggingStateWrapper::debugStack() +QStringList QMachineState::debugStack() { QStringList stack; for (std::vector::reverse_iterator i = m_state.stack.rbegin(); i != m_state.stack.rend(); ++i) @@ -91,7 +89,7 @@ QStringList DebuggingStateWrapper::debugStack() return fillList(stack, ""); } -QStringList DebuggingStateWrapper::debugStorage() +QStringList QMachineState::debugStorage() { QStringList storage; for (auto const& i: m_state.storage) @@ -103,7 +101,7 @@ QStringList DebuggingStateWrapper::debugStorage() return fillList(storage, "@ -"); } -QVariantList DebuggingStateWrapper::debugMemory() +QVariantList QMachineState::debugMemory() { std::vector> dump = memDumpToList(m_state.memory, 16); QStringList filled; @@ -113,17 +111,17 @@ QVariantList DebuggingStateWrapper::debugMemory() return fillList(qVariantDump(dump), QVariant(filled)); } -QVariantList DebuggingStateWrapper::debugCallData() +QCallData* QMachineState::getDebugCallData(QObject* _owner, bytes const& _data) { - std::vector> dump = memDumpToList(m_data, 16); + std::vector> dump = memDumpToList(_data, 16); QStringList filled; filled.append(" "); filled.append(" "); filled.append(" "); - return fillList(qVariantDump(dump), QVariant(filled)); + return new QCallData(_owner, fillList(qVariantDump(dump), QVariant(filled))); } -std::vector> DebuggingStateWrapper::memDumpToList(bytes const& _bytes, unsigned _width) +std::vector> QMachineState::memDumpToList(bytes const& _bytes, unsigned _width) { std::vector> dump; for (unsigned i = 0; i < _bytes.size(); i += _width) @@ -155,7 +153,7 @@ std::vector> DebuggingStateWrapper::memDumpToList(bytes return dump; } -QVariantList DebuggingStateWrapper::qVariantDump(std::vector> const& _dump) +QVariantList QMachineState::qVariantDump(std::vector> const& _dump) { QVariantList ret; for (std::vector const& line: _dump) @@ -168,7 +166,7 @@ QVariantList DebuggingStateWrapper::qVariantDump(std::vector m_state.gas) return QApplication::tr("OUT-OF-GAS"); diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 0541f0afa..d7591ea4e 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -39,45 +39,61 @@ namespace mix /** * @brief Contains the line nb of the assembly code and the corresponding index in the code bytes array. */ -class HumanReadableCode: public QObject +class QInstruction: public QObject { Q_OBJECT - Q_PROPERTY(QString line READ line CONSTANT) - Q_PROPERTY(int processIndex READ processIndex CONSTANT) + Q_PROPERTY(QString line MEMBER m_line CONSTANT) + Q_PROPERTY(int processIndex MEMBER m_processIndex CONSTANT) public: - HumanReadableCode(QString _line, int _processIndex): QObject(), m_line(_line), m_processIndex(_processIndex) {} - /// Get the assembly code line. - QString line() { return m_line; } - /// Get corresponding index. - int processIndex() { return m_processIndex; } + QInstruction(QObject* _owner, QString _line, int _processIndex): QObject(_owner), m_line(_line), m_processIndex(_processIndex) {} private: QString m_line; int m_processIndex; }; +class QCode: public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantList instructions MEMBER m_instructions CONSTANT) -/** - * @brief Publish QMap type to QML. - */ -class QQMLMap: public QObject +public: + QCode(QObject* _owner, QVariantList&& _instrunctions): QObject(_owner), m_instructions(_instrunctions) {} + +private: + QVariantList m_instructions; +}; + +class QCallData: public QObject { Q_OBJECT + Q_PROPERTY(QVariantList items MEMBER m_items CONSTANT) public: - QQMLMap(QMap _map): QObject(), m_map(_map) { } - /// Get the value associated with _key store in n_map. - Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } + QCallData(QObject* _owner, QVariantList&& _items): QObject(_owner), m_items(_items) {} private: - QMap m_map; + QVariantList m_items; +}; + +class QDebugData: public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantList states MEMBER m_states CONSTANT) + +public: + QDebugData() { } + void setStates(QVariantList&& _states) { m_states = _states; } + +private: + QVariantList m_states; }; /** * @brief Wrap DebuggingState in QObject */ -class DebuggingStateWrapper: public QObject +class QMachineState: public QObject { Q_OBJECT Q_PROPERTY(int step READ step CONSTANT) @@ -88,18 +104,25 @@ class DebuggingStateWrapper: public QObject Q_PROPERTY(QStringList debugStack READ debugStack CONSTANT) Q_PROPERTY(QStringList debugStorage READ debugStorage CONSTANT) Q_PROPERTY(QVariantList debugMemory READ debugMemory CONSTANT) - Q_PROPERTY(QVariantList debugCallData READ debugCallData CONSTANT) - Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT) + Q_PROPERTY(QObject* code MEMBER m_code CONSTANT) + Q_PROPERTY(QObject* callData MEMBER m_callData CONSTANT) Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT) Q_PROPERTY(QBigInt* newMemSize READ newMemSize CONSTANT) Q_PROPERTY(QStringList levels READ levels CONSTANT) + Q_PROPERTY(unsigned codeIndex READ codeIndex CONSTANT) + Q_PROPERTY(unsigned dataIndex READ dataIndex CONSTANT) public: - DebuggingStateWrapper(bytes _code, bytes _data): QObject(), m_code(_code), m_data(_data) {} + QMachineState(QObject* _owner, MachineState const& _state, QCode* _code, QCallData* _callData): + QObject(_owner), m_state(_state), m_code(_code), m_callData(_callData) {} /// Get the step of this machine states. int step() { return (int)m_state.steps; } /// Get the proccessed code index. int curPC() { return (int)m_state.curPC; } + /// Get the code id + unsigned codeIndex() { return m_state.codeIndex; } + /// Get the call data id + unsigned dataIndex() { return m_state.dataIndex; } /// Get gas cost. QBigInt* gasCost(); /// Get gas used. @@ -111,8 +134,6 @@ public: /// Get memory. QVariantList debugMemory(); /// Get call data. - QVariantList debugCallData(); - /// Get info to be displayed in the header. QString headerInfo(); /// get end of debug information. QString endOfDebug(); @@ -126,20 +147,21 @@ public: MachineState state() { return m_state; } /// Set the current processed machine state. void setState(MachineState _state) { m_state = _state; } - /// Convert all machine state in human readable code. - static std::tuple, QQMLMap*> getHumanReadableCode(bytes const& _code); + /// Convert all machine states in human readable code. + static QCode* getHumanReadableCode(QObject* _owner, bytes const& _code); + /// Convert call data into human readable form + static QCallData* getDebugCallData(QObject* _owner, bytes const& _data); private: MachineState m_state; - bytes m_code; - bytes m_data; - QStringList fillList(QStringList& _list, QString const& _emptyValue); - QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); - QVariantList qVariantDump(std::vector> const& _dump); + QCode* m_code; + QCallData* m_callData; + static QStringList fillList(QStringList& _list, QString const& _emptyValue); + static QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); + static QVariantList qVariantDump(std::vector> const& _dump); /// Nicely renders the given bytes to a string, store the content in an array. /// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line. - std::vector> memDumpToList(bytes const& _bytes, unsigned _width); - + static std::vector> memDumpToList(bytes const& _bytes, unsigned _width); }; } diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 81df48fe9..86da3fc0f 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -63,21 +63,46 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) bytes rlp = _t.rlp(); Executive execution(_state, LastHashes(), 0); execution.setup(&rlp); - bytes code; - bytesConstRef data; - bool firstIteration = true; std::vector machineStates; std::vector levels; + std::vector codes; + std::map codeIndexes; + std::vector data; + std::map dataIndexes; + bytes const* lastCode = nullptr; + bytesConstRef const* lastData = nullptr; + unsigned codeIndex = 0; + unsigned dataIndex = 0; 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 (lastCode == nullptr || lastCode != &ext.code) + { + auto const& iter = codeIndexes.find(&ext.code); + if (iter != codeIndexes.end()) + codeIndex = iter->second; + else + { + codeIndex = codes.size(); + codes.push_back(ext.code); + codeIndexes[&ext.code] = codeIndex; + } + lastCode = &ext.code; + } - if (firstIteration) + if (lastData == nullptr || lastData != &ext.data) { - code = ext.code; - data = ext.data; - firstIteration = false; + auto const& iter = dataIndexes.find(&ext.data); + if (iter != dataIndexes.end()) + dataIndex = iter->second; + else + { + dataIndex = data.size(); + data.push_back(ext.data.toBytes()); + dataIndexes[&ext.data] = dataIndex; + } + lastData = &ext.data; } if (levels.size() < ext.depth) @@ -85,8 +110,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) else levels.resize(ext.depth); - machineStates.push_back(MachineState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), - vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); + machineStates.emplace_back(MachineState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), + vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels, codeIndex, dataIndex})); }; execution.go(onOp); @@ -95,9 +120,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) ExecutionResult d; d.returnValue = execution.out().toVector(); d.machineStates = machineStates; - d.executionCode = code; - d.executionData = data; - d.transactionData = _t.data(); + d.executionCode = std::move(codes); + d.transactionData = std::move(data); d.address = _t.receiveAddress(); d.sender = _t.sender(); d.value = _t.value(); diff --git a/mix/MixClient.h b/mix/MixClient.h index 54dff0f3a..86a0860e6 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -38,7 +38,7 @@ namespace mix struct MachineState { uint64_t steps; - dev::Address cur; + dev::Address address; dev::u256 curPC; dev::eth::Instruction inst; dev::bigint newMemSize; @@ -48,6 +48,8 @@ struct MachineState dev::bigint gasCost; std::map storage; std::vector levels; + unsigned codeIndex; + unsigned dataIndex; }; /** @@ -58,9 +60,8 @@ struct ExecutionResult ExecutionResult(): receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} std::vector machineStates; - bytes transactionData; - bytes executionCode; - bytesConstRef executionData; + std::vector transactionData; + std::vector executionCode; bytes returnValue; dev::Address address; dev::Address sender; diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 592e7eb26..11b6b6bf0 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -27,11 +27,11 @@ Rectangle { forceActiveFocus(); } - function update(giveFocus) + function update(data, giveFocus) { if (statusPane.result.successful) { - Debugger.init(); + Debugger.init(data); debugScrollArea.visible = true; compilationErrorArea.visible = false; machineStates.visible = true; @@ -50,9 +50,16 @@ Rectangle { forceActiveFocus(); } + Connections { + target: clientModel + onDebugDataReady: { + update(_debugData, true); + } + } + Connections { target: codeModel - onCompilationComplete: update(false) + onCompilationComplete: update(null, false); } Rectangle @@ -277,6 +284,7 @@ Rectangle { delegate: renderDelegate highlight: highlightBar highlightFollowsCurrentItem: false + model: ListModel {} } Component { diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index 9078befdb..9f561b173 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -1,35 +1,53 @@ -//humanReadableExecutionCode => contain human readable code. -//debugStates => contain all debug states. -//bytesCodeMapping => mapping between humanReadableExecutionCode and bytesCode. +//debugData => contain all debug states. //statesList => ListView var currentSelectedState = null; var jumpStartingPoint = null; -function init() +var debugData = null; +var codeMap = null; + +function init(data) { - if (typeof(debugStates) === "undefined") + jumpOutBackAction.enabled(false); + jumpIntoBackAction.enabled(false); + jumpIntoForwardAction.enabled(false); + jumpOutForwardAction.enabled(false); + + if (data === null) { + statesList.model.clear(); + statesSlider.maximumValue = 0; + statesSlider.value = 0; + currentSelectedState = null; + jumpStartingPoint = null; + debugData = null; return; + } - statesSlider.maximumValue = debugStates.length - 1; + debugData = data; + statesSlider.maximumValue = data.states.length - 1; statesSlider.value = 0; - statesList.model = humanReadableExecutionCode; currentSelectedState = 0; + setupInstructions(currentSelectedState); select(currentSelectedState); +} - jumpOutBackAction.enabled(false); - jumpIntoBackAction.enabled(false); - jumpIntoForwardAction.enabled(false); - jumpOutForwardAction.enabled(false); +function setupInstructions(stateIndex) { + + var instructions = debugData.states[stateIndex].code.instructions; + codeMap = {}; + statesList.model.clear(); + for (var i = 0; i < instructions.length; i++) { + statesList.model.append(instructions[i]); + codeMap[instructions[i].processIndex] = i; + } } function moveSelection(incr) { - if (typeof(debugStates) === "undefined") - return; - + var prevState = currentSelectedState; if (currentSelectedState + incr >= 0) { - if (currentSelectedState + incr < debugStates.length) + if (currentSelectedState + incr < debugData.states.length) select(currentSelectedState + incr); statesSlider.value = currentSelectedState; } @@ -37,16 +55,15 @@ function moveSelection(incr) function select(stateIndex) { - if (typeof(debugStates) === "undefined") - return; - + if (debugData.states[stateIndex].codeIndex !== debugData.states[currentSelectedState].codeIndex) + setupInstructions(stateIndex); + currentSelectedState = stateIndex; var codeLine = codeStr(stateIndex); - var state = debugStates[stateIndex]; + var state = debugData.states[stateIndex]; highlightSelection(codeLine); - currentSelectedState = stateIndex; completeCtxInformation(state); - if (state.instruction === "JUMP") + if (state.instruction === "CALL" || state.instruction === "CREATE") jumpIntoForwardAction.enabled(true); else jumpIntoForwardAction.enabled(false); @@ -59,11 +76,8 @@ function select(stateIndex) function codeStr(stateIndex) { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[stateIndex]; - return bytesCodeMapping.getValue(state.curPC); + var state = debugData.states[stateIndex]; + return codeMap[state.curPC]; } function highlightSelection(index) @@ -73,13 +87,10 @@ function highlightSelection(index) function completeCtxInformation(state) { - if (typeof(debugStates) === "undefined") - return; - currentStep.update(state.step); mem.update(state.newMemSize.value() + " " + qsTr("words")); stepCost.update(state.gasCost.value()); - gasSpent.update(debugStates[0].gas.subtract(state.gas).value()); + gasSpent.update(debugData.states[0].gas.subtract(state.gas).value()); stack.listModel = state.debugStack; storage.listModel = state.debugStorage; @@ -87,17 +98,8 @@ function completeCtxInformation(state) callDataDump.listModel = state.debugCallData; } -function displayReturnValue() -{ - headerReturnList.model = contractCallReturnParameters; - headerReturnList.update(); -} - function stepOutBack() { - if (typeof(debugStates) === "undefined") - return; - if (jumpStartingPoint != null) { select(jumpStartingPoint); @@ -114,15 +116,12 @@ function stepIntoBack() function stepOverBack() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMPDEST") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { for (var k = currentSelectedState; k > 0; k--) { - var line = bytesCodeMapping.getValue(debugStates[k].curPC); + var line = codeMap[debugData.states[k].curPC]; if (line === statesList.currentIndex - 2) { select(k); @@ -136,15 +135,12 @@ function stepOverBack() function stepOverForward() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMP") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { - for (var k = currentSelectedState; k < debugStates.length; k++) + for (var k = currentSelectedState; k < debugData.states.length; k++) { - var line = bytesCodeMapping.getValue(debugStates[k].curPC); + var line = codeMap[debugData.states[k].curPC]; if (line === statesList.currentIndex + 2) { select(k); @@ -158,11 +154,8 @@ function stepOverForward() function stepIntoForward() { - if (typeof(debugStates) === "undefined") - return; - - var state = debugStates[currentSelectedState]; - if (state.instruction === "JUMP") + var state = debugData.states[currentSelectedState]; + if (state.instruction === "CALL" || state.instruction === "CREATE") { jumpStartingPoint = currentSelectedState; moveSelection(1); @@ -184,6 +177,5 @@ function stepOutForward() function jumpTo(value) { - currentSelectedState = value; - select(currentSelectedState); + select(value); }