diff --git a/cmake/FindCURL.cmake b/cmake/FindCURL.cmake index e2f52fe79..f9d2693ec 100644 --- a/cmake/FindCURL.cmake +++ b/cmake/FindCURL.cmake @@ -39,6 +39,13 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(CURL_LIBRARIES optimized ${CURL_LIBRARIES} debug ${CURL_LIBRARY_DEBUG}) + # prepare dlls + string(REPLACE ".lib" ".dll" CURL_DLL ${CURL_LIBRARY}) + string(REPLACE "/lib/" "/bin/" CURL_DLL ${CURL_DLL}) + string(REPLACE ".lib" ".dll" CURL_DLL_DEBUG ${CURL_LIBRARY_DEBUG}) + string(REPLACE "/lib/" "/bin/" CURL_DLL_DEBUG ${CURL_DLL_DEBUG}) + set(CURL_DLLS optimized ${CURL_DLL} debug ${CURL_DLL_DEBUG}) + endif() # handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 75e0b9e04..649d7a2d3 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -22,8 +22,10 @@ if (READLINE_FOUND) endif() if (JSONRPC) - target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) target_link_libraries(${EXECUTABLE} web3jsonrpc) + target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) + target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) + eth_copy_dlls(${EXECUTABLE} CURL_DLLS) endif() target_link_libraries(${EXECUTABLE} webthree) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 807c27adf..3478a88fa 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -401,9 +401,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex]; auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end)); if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty())) - solCallStack.push_back(QVariant::fromValue(functionIter.value())); + solCallStack.push_front(QVariant::fromValue(functionIter.value())); else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty()) - solCallStack.pop_back(); + solCallStack.pop_front(); } //format solidity context values diff --git a/mix/HttpServer.cpp b/mix/HttpServer.cpp index bf210444b..968580907 100644 --- a/mix/HttpServer.cpp +++ b/mix/HttpServer.cpp @@ -106,8 +106,21 @@ void HttpServer::updateListening() if (this->isListening()) this->close(); - if (!m_listen || QTcpServer::listen(QHostAddress::LocalHost, m_port)) + if (!m_listen) return; + + if (!QTcpServer::listen(QHostAddress::LocalHost, m_port)) + { + errorStringChanged(); + return; + } + + if (m_port != QTcpServer::serverPort()) + { + m_port = QTcpServer::serverPort(); + emit portChanged(m_port); + emit urlChanged(url()); + } } void HttpServer::incomingConnection(qintptr _socket) diff --git a/mix/HttpServer.h b/mix/HttpServer.h index add83238b..8a1e4553a 100644 --- a/mix/HttpServer.h +++ b/mix/HttpServer.h @@ -100,7 +100,7 @@ protected: signals: void clientConnected(HttpRequest* _request); - void errorStringChanged(QString const& _errorString); + void errorStringChanged(); void urlChanged(QUrl const& _url); void portChanged(int _port); void listenChanged(bool _listen); diff --git a/mix/qml/DebugInfoList.qml b/mix/qml/DebugInfoList.qml index b479d6d28..9adac7b5c 100644 --- a/mix/qml/DebugInfoList.qml +++ b/mix/qml/DebugInfoList.qml @@ -33,7 +33,11 @@ ColumnLayout { if (storageContainer.parent.parent.height === 25) storageContainer.collapse(); else + { + if (storageContainer.parent.parent.height === 0) + storageContainer.parent.parent.height = 200; storageContainer.expand(); + } } RowLayout { @@ -63,6 +67,8 @@ ColumnLayout { if (collapsed) { storageContainer.expand(); + if (storedHeight <= 25) + storedHeight = 200; storageContainer.parent.parent.height = storedHeight; } else @@ -105,8 +111,6 @@ ColumnLayout { height: parent.height - 6 onHeightChanged: { if (height <= 0 && collapsible) { - if (storedHeight <= 0) - storedHeight = 200; storageContainer.collapse(); } else if (height > 0 && collapsed) { diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 3b8a87e8a..87a27cf79 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -17,6 +17,10 @@ Rectangle { property alias solLocals: solLocals property alias solStorage: solStorage property alias solCallStack: solCallStack + property alias vmCallStack: callStack + property alias vmStorage: storage + property alias vmMemory: memoryDump + property alias vmCallData: callDataDump signal debugExecuteLocation(string documentId, var location) property string compilationErrorMessage property bool assemblyMode: false diff --git a/mix/qml/NewProjectDialog.qml b/mix/qml/NewProjectDialog.qml index 611f18049..77b6c513a 100644 --- a/mix/qml/NewProjectDialog.qml +++ b/mix/qml/NewProjectDialog.qml @@ -28,6 +28,7 @@ Item Dialog { id: newProjectWin modality: Qt.ApplicationModal + title: qsTr("New Project"); width: 640 height: 120 diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 58bb3c64d..44f96a775 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -40,11 +40,14 @@ Item { var contracts = {}; for (var c in codeModel.contracts) { var contract = codeModel.contracts[c]; - contracts[c] = { - name: contract.contract.name, - address: clientModel.contractAddresses[contract.contract.name], - interface: JSON.parse(contract.contractInterface), - }; + var address = clientModel.contractAddresses[contract.contract.name]; + if (address) { + contracts[c] = { + name: contract.contract.name, + address: address, + interface: JSON.parse(contract.contractInterface), + }; + } } webView.runJavaScript("updateContracts(" + JSON.stringify(contracts) + ")"); } @@ -150,7 +153,6 @@ Item { id: httpServer listen: true accept: true - port: 8893 onClientConnected: { var urlPath = _request.url.toString(); if (urlPath.indexOf("/rpc/") === 0) diff --git a/mix/test/qml/TestMain.qml b/mix/test/qml/TestMain.qml index d1d962900..73cff824e 100644 --- a/mix/test/qml/TestMain.qml +++ b/mix/test/qml/TestMain.qml @@ -50,12 +50,21 @@ TestCase function editContract(c) { + if (mainApplication.codeModel.compiling) + ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000); mainApplication.mainContent.codeEditor.getEditor("contract.sol").setText(c); if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000)) fail("not compiled"); ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S } + + function waitForExecution() + { + while (mainApplication.clientModel.running) + ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000); + } + function editHtml(c) { mainApplication.projectModel.openDocument("index.html"); @@ -76,6 +85,8 @@ TestCase function test_dbg_transactionWithParameter() { TestDebugger.test_transactionWithParameter(); } function test_dbg_constructorParameters() { TestDebugger.test_constructorParameters(); } function test_dbg_arrayParametersAndStorage() { TestDebugger.test_arrayParametersAndStorage(); } + function test_dbg_solidity() { TestDebugger.test_solidityDebugging(); } + function test_dbg_vm() { TestDebugger.test_vmDebugging(); } function test_miner_getDefaultiner() { TestMiner.test_getDefaultMiner(); } function test_miner_selectMiner() { TestMiner.test_selectMiner(); } function test_project_contractRename() { TestProject.test_contractRename(); } diff --git a/mix/test/qml/js/TestDebugger.js b/mix/test/qml/js/TestDebugger.js index 747b7b76d..706601d18 100644 --- a/mix/test/qml/js/TestDebugger.js +++ b/mix/test/qml/js/TestDebugger.js @@ -14,8 +14,7 @@ function test_defaultTransactionSequence() " uint z;\r" + "}\r" ); - if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000)) - fail("Error running transaction"); + waitForExecution(); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 3); } @@ -47,8 +46,7 @@ function test_transactionWithParameter() transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000)) - fail("Error running transaction"); + waitForExecution(); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 5); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "returned", "(442)"); } @@ -79,8 +77,7 @@ function test_constructorParameters() transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.mainContent.startQuickDebugging(); - if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000)) - fail("Error running transaction"); + waitForExecution(); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 4); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(3), "returned", "(442)"); } @@ -137,3 +134,67 @@ function test_arrayParametersAndStorage() tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "s", "42"); tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 0, "setMV"); } + +function test_solidityDebugging() +{ + newProject(); + editContract( + "contract Contract {\r " + + " function add(uint256 a, uint256 b) returns (uint256)\r " + + " {\r " + + " return a + b;\r " + + " }\r " + + " function Contract()\r " + + " {\r " + + " uint256 local = add(42, 34);\r " + + " storage = local;\r " + + " }\r " + + " uint256 storage;\r " + + "}"); + + mainApplication.mainContent.startQuickDebugging(); + if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) + fail("Error running transaction"); + + tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 20); + tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0); + mainApplication.mainContent.rightPane.debugSlider.value = 13; + tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 0, "add"); + tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 1, "Contract"); + tryCompare(mainApplication.mainContent.rightPane.solLocals.item.value, "local", "0"); + tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "storage", undefined); + mainApplication.mainContent.rightPane.debugSlider.value = 19; + tryCompare(mainApplication.mainContent.rightPane.solLocals.item.value, "local", "76"); + tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "storage", "76"); +} + +function test_vmDebugging() +{ + newProject(); + editContract( + "contract Contract {\r " + + " function add(uint256 a, uint256 b) returns (uint256)\r " + + " {\r " + + " return a + b;\r " + + " }\r " + + " function Contract()\r " + + " {\r " + + " uint256 local = add(42, 34);\r " + + " storage = local;\r " + + " }\r " + + " uint256 storage;\r " + + "}"); + + mainApplication.mainContent.startQuickDebugging(); + if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000)) + fail("Error running transaction"); + + mainApplication.mainContent.rightPane.assemblyMode = !mainApplication.mainContent.rightPane.assemblyMode; + tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 41); + tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0); + mainApplication.mainContent.rightPane.debugSlider.value = 35; + tryCompare(mainApplication.mainContent.rightPane.vmCallStack.listModel, 0, mainApplication.clientModel.contractAddresses["Contract"].substring(2)); + tryCompare(mainApplication.mainContent.rightPane.vmStorage.listModel, 0, "@ 0 (0x0) 76 (0x4c)"); + tryCompare(mainApplication.mainContent.rightPane.vmMemory.listModel, "length", 0); +} + diff --git a/mix/test/qml/js/TestProject.js b/mix/test/qml/js/TestProject.js index d81b72942..444760ea3 100644 --- a/mix/test/qml/js/TestProject.js +++ b/mix/test/qml/js/TestProject.js @@ -3,8 +3,8 @@ function test_contractRename() newProject(); tryCompare(mainApplication.mainContent.projectNavigator.sections.itemAt(0).model.get(0), "name", "Contract"); editContract("contract Renamed {}"); - if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000)) - fail("Error running transaction"); + mainApplication.mainContent.startQuickDebugging(); + waitForExecution(); wait(1000); tryCompare(mainApplication.mainContent.projectNavigator.sections.itemAt(0).model.get(0), "name", "Renamed"); mainApplication.projectModel.stateListModel.editState(0);