From eab54c8d1d12f2220bf4a016cc852e6b77f3c86d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 10 Aug 2015 16:47:42 +0200 Subject: [PATCH 01/16] compile code in accounts when importing state --- libethereum/Account.cpp | 3 ++- test/TestHelper.cpp | 17 ++++++++++++++--- test/libethereum/state.cpp | 17 +++-------------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/libethereum/Account.cpp b/libethereum/Account.cpp index 44b5079ea..4297ec479 100644 --- a/libethereum/Account.cpp +++ b/libethereum/Account.cpp @@ -21,6 +21,7 @@ #include "Account.h" #include +#include #include using namespace std; using namespace dev; @@ -63,7 +64,7 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, AccountMaskMap* if (haveCode) { ret[a] = Account(balance, Account::ContractConception); - ret[a].setCode(fromHex(o["code"].get_str())); + ret[a].setCode(test::importCode(o)); } else ret[a] = Account(balance, Account::NormalCreation); diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 399779756..0b9f1e0ef 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -121,10 +121,21 @@ bytes ImportTest::executeTest() { ExecutionResult res; eth::State tmpState = m_statePre; + try + { + std::pair execOut = m_statePre.execute(m_envInfo, m_transaction); + res = execOut.first; + m_logs = execOut.second.log(); + } + catch (Exception const& _e) + { + cnote << "Exception: " << diagnostic_information(_e); + } + catch (std::exception const& _e) + { + cnote << "state execution exception: " << _e.what(); + } - std::pair execOut = m_statePre.execute(m_envInfo, m_transaction); - res = execOut.first; - m_logs = execOut.second.log(); m_statePre.commit(); m_statePost = m_statePre; m_statePre = tmpState; diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index f0653401e..4c9d998b2 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -59,20 +59,9 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) const State importedStatePost = importer.m_statePost; bytes output; - try - { - Listener::ExecTimeGuard guard{i.first}; - output = importer.executeTest(); - } - catch (Exception const& _e) - { - cnote << "Exception: " << diagnostic_information(_e); - //theState.commit(); - } - catch (std::exception const& _e) - { - cnote << "state execution exception: " << _e.what(); - } + // execute transaction + Listener::ExecTimeGuard guard{i.first}; + output = importer.executeTest(); if (_fillin) { From 50cc9d12561a98b6c03a6148251a966e2e8d3049 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 11 Aug 2015 11:05:52 +0200 Subject: [PATCH 02/16] fix compile --- libethereum/Account.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libethereum/Account.cpp b/libethereum/Account.cpp index 4297ec479..727c35a47 100644 --- a/libethereum/Account.cpp +++ b/libethereum/Account.cpp @@ -20,8 +20,8 @@ */ #include "Account.h" +#include #include -#include #include using namespace std; using namespace dev; @@ -64,7 +64,15 @@ AccountMap dev::eth::jsonToAccountMap(std::string const& _json, AccountMaskMap* if (haveCode) { ret[a] = Account(balance, Account::ContractConception); - ret[a].setCode(test::importCode(o)); + if (o["code"].type() == json_spirit::str_type) + { + if (o["code"].get_str().find("0x") != 0) + ret[a].setCode(compileLLL(o["code"].get_str(), false)); + else + ret[a].setCode(fromHex(o["code"].get_str().substr(2))); + } + else + cerr << "Error importing code of account " << a << "! Code field needs to be a string"; } else ret[a] = Account(balance, Account::NormalCreation); From 502e191ac92cf1d7b30c312dbd14821157fc1a14 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 11 Aug 2015 11:33:09 +0200 Subject: [PATCH 03/16] clean up --- test/libethereum/blockchain.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 5647ece4e..0be4d6622 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -51,14 +51,6 @@ void overwriteBlockHeader(BlockHeader& _current_BlockHeader, mObject& _blObj, co void updatePoW(BlockHeader& _bi); mArray importUncles(mObject const& _blObj, vector& _vBiUncles, vector const& _vBiBlocks, std::vector _blockSet); -//void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) -//{ -// if (_fillin == false) -// _v.get_bool(); - -// cerr << "BlockChainTests not implemented!" << endl; -//} - void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { for (auto& i: _v.get_obj()) From 618189fb7c0d6ebdfd6a0ccabbc29af7ff7b9b7e Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 6 Aug 2015 14:31:13 +0200 Subject: [PATCH 04/16] solidity builtins auto-completion and syntax highlight --- mix/qml/html/cm/anyword-hint.js | 9 +++++++++ mix/qml/html/cm/inkpot.css | 2 +- mix/qml/html/cm/solidity.js | 2 ++ mix/qml/html/cm/solidityToken.js | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mix/qml/html/cm/anyword-hint.js b/mix/qml/html/cm/anyword-hint.js index d1034ed8c..050d59ddf 100644 --- a/mix/qml/html/cm/anyword-hint.js +++ b/mix/qml/html/cm/anyword-hint.js @@ -24,6 +24,15 @@ list = addSolToken(curWord, list, seen, solMisc(), solMisc); } + //TODO: tokenize properly + if (curLine.slice(start - 6, start) === "block.") + list = addSolToken(curWord, list, seen, solBlock(), solBlock); + else if (curLine.slice(start - 4, start) === "msg.") + list = addSolToken(curWord, list, seen, solMsg(), solMsg); + else if (curLine.slice(start - 3, start) === "tx.") + list = addSolToken(curWord, list, seen, solTx(), solTx); + + var previousWord = ""; var re = new RegExp(word.source, "g"); for (var dir = -1; dir <= 1; dir += 2) { diff --git a/mix/qml/html/cm/inkpot.css b/mix/qml/html/cm/inkpot.css index b31e20ad8..4a2197cfc 100644 --- a/mix/qml/html/cm/inkpot.css +++ b/mix/qml/html/cm/inkpot.css @@ -21,7 +21,7 @@ https://github.com/ciaranm/inkpot .cm-s-inkpot span.cm-comment { color: #cd8b00; } .cm-s-inkpot span.cm-def { color: #cfbfad; font-weight:bold; } .cm-s-inkpot span.cm-keyword { color: #808bed; } -.cm-s-inkpot span.cm-builtin { color: #cfbfad; } +.cm-s-inkpot span.cm-builtin { color: #efac6d; } .cm-s-inkpot span.cm-variable { color: #cfbfad; } .cm-s-inkpot span.cm-string { color: #ffcd8b; } .cm-s-inkpot span.cm-number { color: #f0ad6d; } diff --git a/mix/qml/html/cm/solidity.js b/mix/qml/html/cm/solidity.js index e1cfeefbb..23f1e460c 100644 --- a/mix/qml/html/cm/solidity.js +++ b/mix/qml/html/cm/solidity.js @@ -16,6 +16,7 @@ CodeMirror.defineMode("solidity", function(config) { var stdContract = solStdContract(); var keywords = solKeywords(); var atoms = solMisc(); + var builtins = solBuiltIn(); var isOperatorChar = /[+\-*&^%:=<>!|\/]/; @@ -64,6 +65,7 @@ CodeMirror.defineMode("solidity", function(config) { if (atoms.propertyIsEnumerable(cur)) return "atom"; if (types.propertyIsEnumerable(cur)) return "variable-2"; if (stdContract.propertyIsEnumerable(cur)) return "variable-3"; + if (builtins.propertyIsEnumerable(cur)) return "builtin"; return "variable"; } diff --git a/mix/qml/html/cm/solidityToken.js b/mix/qml/html/cm/solidityToken.js index 1c12278e1..fbed0287e 100644 --- a/mix/qml/html/cm/solidityToken.js +++ b/mix/qml/html/cm/solidityToken.js @@ -28,6 +28,26 @@ function solMisc() return { "true": true, "false": true, "null": true }; } +function solBuiltIn() +{ + return { "msg": true, "tx": true, "block": true, "now": true }; +} + +function solBlock() +{ + return { "coinbase": true, "difficulty": true, "gaslimit": true, "number": true, "blockhash": true, "timestamp":true }; +} + +function solMsg() +{ + return { "data": true, "gas": true, "sender": true, "sig": true, "value": true }; +} + +function solTx() +{ + return { "gasprice": true, "origin": true } +} + function keywordsName() { var keywords = {}; @@ -37,5 +57,9 @@ function keywordsName() keywords[solTime.name.toLowerCase()] = "Time"; keywords[solTypes.name.toLowerCase()] = "Type"; keywords[solMisc.name.toLowerCase()] = "Misc"; + keywords[solBuiltIn.name.toLowerCase()] = "BuiltIn"; + keywords[solBlock.name.toLowerCase()] = "Block"; + keywords[solMsg.name.toLowerCase()] = "Message"; + keywords[solTx.name.toLowerCase()] = "Transaction"; return keywords; } From 7d550846ed7ff649c1a538b87cf3682e98d610fd Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 10 Aug 2015 15:41:24 +0200 Subject: [PATCH 05/16] custom file dialog to work around qt 5.5 bug --- mix/CMakeLists.txt | 5 + mix/FileIo.cpp | 8 + mix/FileIo.h | 5 + mix/MixApplication.cpp | 3 + mix/MixClient.cpp | 2 +- mix/osx.qrc | 5 + mix/qml.qrc | 1 + mix/qml/Application.qml | 6 +- mix/qml/MacFileDialog.qml | 298 +++++++++++++++++++++++++++++++++++ mix/qml/NewProjectDialog.qml | 2 +- mix/qml/PackagingStep.qml | 3 +- mix/qml/QFileDialog.qml | 5 + mix/qml/StateDialog.qml | 2 +- 13 files changed, 339 insertions(+), 6 deletions(-) create mode 100644 mix/osx.qrc create mode 100644 mix/qml/MacFileDialog.qml create mode 100644 mix/qml/QFileDialog.qml diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 44cd9c12a..874656f89 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -20,6 +20,11 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND NOT (CMAKE_CXX_COMPILER_VER set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") endif () +#TODO: remove once qt 5.5.1 is out +if (APPLE) + qt5_add_resources(UI_RESOURCES osx.qrc) +endif() + find_package (Qt5WebEngine) if (APPLE) # TODO: remove indirect dependencies once macdeployqt is fixed diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index 1c9faa896..525715d5a 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -224,3 +224,11 @@ void FileIo::deleteFile(QString const& _path) QFile file(pathFromUrl(_path)); file.remove(); } + +QUrl FileIo::pathFolder(QString const& _path) +{ + QFileInfo info(_path); + if (info.exists() && info.isDir()) + return QUrl::fromLocalFile(_path); + return QUrl::fromLocalFile(QFileInfo(_path).absolutePath()); +} diff --git a/mix/FileIo.h b/mix/FileIo.h index eb5bc6cad..0db399a73 100644 --- a/mix/FileIo.h +++ b/mix/FileIo.h @@ -71,6 +71,11 @@ public: /// delete a directory Q_INVOKABLE void deleteDir(QString const& _url); + //TODO: remove once qt 5.5.1 is out + Q_INVOKABLE QString urlToPath(QUrl const& _url) { return _url.toLocalFile(); } + Q_INVOKABLE QUrl pathToUrl(QString const& _path) { return QUrl::fromLocalFile(_path); } + Q_INVOKABLE QUrl pathFolder(QString const& _path); + private: QString getHomePath() const; QString pathFromUrl(QString const& _url); diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index d81a4f6b2..4972b6cf5 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -41,6 +41,9 @@ extern int qInitResources_js(); using namespace dev::mix; + + + ApplicationService::ApplicationService() { #ifdef ETH_HAVE_WEBENGINE diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 4f4139701..89b749629 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -284,7 +284,7 @@ void MixClient::mine() RLPStream header; h.streamRLP(header); m_postMine.sealBlock(header.out()); - bc().import(m_postMine.blockData(), m_stateDB, ImportRequirements::Everything & ~ImportRequirements::ValidSeal); + bc().import(m_postMine.blockData(), m_stateDB, (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0); m_postMine.sync(bc()); m_preMine = m_postMine; } diff --git a/mix/osx.qrc b/mix/osx.qrc new file mode 100644 index 000000000..ef302c2d5 --- /dev/null +++ b/mix/osx.qrc @@ -0,0 +1,5 @@ + + + qml/MacFileDialog.qml + + diff --git a/mix/qml.qrc b/mix/qml.qrc index c1901c220..50795d08b 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -34,6 +34,7 @@ qml/QStringTypeView.qml qml/QVariableDeclaration.qml qml/QVariableDefinition.qml + qml/QFileDialog.qml qml/SourceSansProBold.qml qml/SourceSansProLight.qml qml/SourceSansProRegular.qml diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml index 188d87be9..b05673ce8 100644 --- a/mix/qml/Application.qml +++ b/mix/qml/Application.qml @@ -281,11 +281,12 @@ ApplicationWindow { onTriggered: openProjectFileDialog.open() } - FileDialog { + QFileDialog { id: openProjectFileDialog visible: false title: qsTr("Open a Project") selectFolder: true + selectExisting: true onAccepted: { var path = openProjectFileDialog.fileUrl.toString(); path += "/"; @@ -333,11 +334,12 @@ ApplicationWindow { onTriggered: addExistingFileDialog.open() } - FileDialog { + QFileDialog { id: addExistingFileDialog visible: false title: qsTr("Add a File") selectFolder: false + selectExisting: true onAccepted: { var paths = addExistingFileDialog.fileUrls; projectModel.addExistingFiles(paths); diff --git a/mix/qml/MacFileDialog.qml b/mix/qml/MacFileDialog.qml new file mode 100644 index 000000000..f1995588f --- /dev/null +++ b/mix/qml/MacFileDialog.qml @@ -0,0 +1,298 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Private 1.0 as ControlsPrivate +import QtQuick.Dialogs 1.2 +import QtQuick.Dialogs.Private 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.1 +import Qt.labs.folderlistmodel 2.1 +import Qt.labs.settings 1.0 + +AbstractDialog { + + id: root + + property string folder: view.model.folder + property var nameFilters: [] + property bool selectFolder: false + property bool selectExisting: true + property int selectedNameFilterIndex: -1 + property var selectedNameFilterExtensions: [] + property string selection: "" + property alias fileUrl: root.selection + + + function selectNameFilter(text) { + } + + function clearSelection(text) { + selection = ""; + } + + function addSelection(text) { + selection = text; + } + + onVisibleChanged: { + if (visible) { + view.needsWidthAdjustment = true + view.selection.clear() + view.focus = true + } + } + + Component.onCompleted: { + folder = fileIo.pathToUrl(fileIo.homePath); + view.model.nameFilters = root.selectedNameFilterExtensions + filterField.currentIndex = root.selectedNameFilterIndex + root.favoriteFolders = settings.favoriteFolders + } + + Component.onDestruction: { + settings.favoriteFolders = root.favoriteFolders + } + + property Settings settings: Settings { + category: "QQControlsFileDialog" + property alias width: root.width + property alias height: root.height + property variant favoriteFolders: [] + } + + property bool showFocusHighlight: false + property SystemPalette palette: SystemPalette { } + property var favoriteFolders: [] + + function dirDown(path) { + view.selection.clear() + root.folder = "file://" + path + } + function dirUp() { + view.selection.clear() + if (view.model.parentFolder != "") + root.folder = view.model.parentFolder + } + function acceptSelection() { + // transfer the view's selections to QQuickFileDialog + clearSelection() + if (selectFolder && view.selection.count === 0) + addSelection(folder) + else { + view.selection.forEach(function(idx) { + if (view.model.isFolder(idx)) { + if (selectFolder) + addSelection(view.model.get(idx, "fileURL")) + } else { + if (!selectFolder) + addSelection(view.model.get(idx, "fileURL")) + } + }) + } + accept() + } + + property Action dirUpAction: Action { + text: "\ue810" + shortcut: "Ctrl+U" + onTriggered: dirUp() + tooltip: qsTr("Go up to the folder containing this one") + } + + Rectangle { + id: window + implicitWidth: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 100, view.implicitWidth)) + implicitHeight: Math.min(root.__maximumDimension, Screen.pixelDensity * 80) + color: root.palette.window + + Binding { + target: view.model + property: "folder" + value: root.folder + } + Binding { + target: currentPathField + property: "text" + value: fileIo.urlToPath(root.folder) + } + Keys.onPressed: { + event.accepted = true + switch (event.key) { + case Qt.Key_Back: + case Qt.Key_Escape: + reject() + break + default: + event.accepted = false + break + } + } + Keys.forwardTo: [view.flickableItem] + + + TableView { + id: view + sortIndicatorVisible: true + width: parent.width + anchors.top: titleBar.bottom + anchors.bottom: bottomBar.top + + property bool needsWidthAdjustment: true + selectionMode: root.selectMultiple ? + (ControlsPrivate.Settings.hasTouchScreen ? SelectionMode.MultiSelection : SelectionMode.ExtendedSelection) : + SelectionMode.SingleSelection + onRowCountChanged: if (needsWidthAdjustment && rowCount > 0) { + resizeColumnsToContents() + needsWidthAdjustment = false + } + model: FolderListModel { + showFiles: !root.selectFolder + nameFilters: root.selectedNameFilterExtensions + sortField: (view.sortIndicatorColumn === 0 ? FolderListModel.Name : + (view.sortIndicatorColumn === 1 ? FolderListModel.Type : + (view.sortIndicatorColumn === 2 ? FolderListModel.Size : FolderListModel.LastModified))) + sortReversed: view.sortIndicatorOrder === Qt.DescendingOrder + } + + onActivated: if (view.focus) { + if (view.selection.count > 0 && view.model.isFolder(row)) { + dirDown(view.model.get(row, "filePath")) + } else { + root.acceptSelection() + } + } + onClicked: currentPathField.text = view.model.get(row, "filePath") + + + TableViewColumn { + id: fileNameColumn + role: "fileName" + title: qsTr("Filename") + delegate: Item { + implicitWidth: pathText.implicitWidth + pathText.anchors.leftMargin + pathText.anchors.rightMargin + + Text { + id: fileIcon + width: height + verticalAlignment: Text.AlignVCenter + font.family: iconFont.name + property alias unicode: fileIcon.text + FontLoader { id: iconFont; source: "qrc:/QtQuick/Dialogs/qml/icons.ttf"; onNameChanged: console.log("custom font" + name) } + x: 4 + height: parent.height - 2 + unicode: view.model.isFolder(styleData.row) ? "\ue804" : "\ue802" + } + Text { + id: pathText + text: styleData.value + anchors { + left: parent.left + right: parent.right + leftMargin: 36 + 6 + rightMargin: 4 + verticalCenter: parent.verticalCenter + } + color: styleData.textColor + elide: Text.ElideRight + renderType: ControlsPrivate.Settings.isMobile ? Text.QtRendering : Text.NativeRendering + } + } + } + TableViewColumn { + role: "fileSuffix" + title: qsTr("Type", "file type (extension)") + // TODO should not need to create a whole new component just to customize the text value + // something like textFormat: function(text) { return view.model.get(styleData.row, "fileIsDir") ? "folder" : text } + delegate: Item { + implicitWidth: sizeText.implicitWidth + sizeText.anchors.leftMargin + sizeText.anchors.rightMargin + Text { + id: sizeText + text: view.model.get(styleData.row, "fileIsDir") ? "folder" : styleData.value + anchors { + left: parent.left + right: parent.right + leftMargin: 4 + rightMargin: 4 + verticalCenter: parent.verticalCenter + } + color: styleData.textColor + elide: Text.ElideRight + renderType: ControlsPrivate.Settings.isMobile ? Text.QtRendering : Text.NativeRendering + } + } + } + TableViewColumn { + role: "fileSize" + title: qsTr("Size", "file size") + horizontalAlignment: Text.AlignRight + } + TableViewColumn { id: modifiedColumn; role: "fileModified" ; title: qsTr("Modified", "last-modified time") } + TableViewColumn { id: accessedColumn; role: "fileAccessed" ; title: qsTr("Accessed", "last-accessed time") } + } + + ToolBar { + id: titleBar + RowLayout { + anchors.fill: parent + ToolButton { + action: dirUpAction + //style: IconButtonStyle { } + Layout.maximumWidth: height * 1.5 + } + TextField { + id: currentPathField + Layout.fillWidth: true + function doAccept() { + root.clearSelection() + if (root.addSelection(fileIo.pathToUrl(text))) + root.accept() + else + root.folder = fileIo.pathFolder(text) + } + onAccepted: doAccept() + } + } + } + Item { + id: bottomBar + width: parent.width + height: buttonRow.height + buttonRow.spacing * 2 + anchors.bottom: parent.bottom + + Row { + id: buttonRow + anchors.right: parent.right + anchors.rightMargin: spacing + anchors.verticalCenter: parent.verticalCenter + spacing: 4 + ComboBox { + id: filterField + model: root.nameFilters + visible: !selectFolder + width: bottomBar.width - cancelButton.width - okButton.width - parent.spacing * 6 + anchors.verticalCenter: parent.verticalCenter + onCurrentTextChanged: { + root.selectNameFilter(currentText) + view.model.nameFilters = root.selectedNameFilterExtensions + } + } + Button { + id: cancelButton + text: qsTr("Cancel") + onClicked: root.reject() + } + Button { + id: okButton + text: root.selectFolder ? qsTr("Choose") : (selectExisting ? qsTr("Open") : qsTr("Save")) + onClicked: { + if (view.model.isFolder(view.currentIndex) && !selectFolder) + dirDown(view.model.get(view.currentIndex, "filePath")) + else if (!(root.selectExisting)) + currentPathField.doAccept() + else + root.acceptSelection() + } + } + } + } + } +} diff --git a/mix/qml/NewProjectDialog.qml b/mix/qml/NewProjectDialog.qml index 77b6c513a..ab35d5c5e 100644 --- a/mix/qml/NewProjectDialog.qml +++ b/mix/qml/NewProjectDialog.qml @@ -105,7 +105,7 @@ Item } - FileDialog { + QFileDialog { id: createProjectFileDialog visible: false title: qsTr("Please choose a path for the project") diff --git a/mix/qml/PackagingStep.qml b/mix/qml/PackagingStep.qml index 26b5c8540..8ee383f56 100644 --- a/mix/qml/PackagingStep.qml +++ b/mix/qml/PackagingStep.qml @@ -27,11 +27,12 @@ Rectangle { visible = true } - FileDialog { + QFileDialog { id: ressourcesFolder visible: false title: qsTr("Please choose a path") selectFolder: true + selectExisting: true property variant target onAccepted: { var u = ressourcesFolder.fileUrl.toString(); diff --git a/mix/qml/QFileDialog.qml b/mix/qml/QFileDialog.qml new file mode 100644 index 000000000..5ce2ad41c --- /dev/null +++ b/mix/qml/QFileDialog.qml @@ -0,0 +1,5 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 + +FileDialog { } diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index cd19751b6..a2d384b3d 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -124,7 +124,7 @@ Dialog { importJsonFileDialog.open() } } - FileDialog { + QFileDialog { id: importJsonFileDialog visible: false title: qsTr("Select State File") From 328823ea796bf01a2a96f9f1d0ef10e2c488400f Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 11 Aug 2015 11:24:19 +0200 Subject: [PATCH 06/16] node address setting --- mix/qml/Application.qml | 3 +++ mix/qml/js/TransactionHelper.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml index b05673ce8..f75646e5b 100644 --- a/mix/qml/Application.qml +++ b/mix/qml/Application.qml @@ -217,6 +217,7 @@ ApplicationWindow { shortcut: "Ctrl+Alt+V" onTriggered: mainContent.debuggerPanel.assemblyMode = !mainContent.debuggerPanel.assemblyMode; checked: mainContent.debuggerPanel.assemblyMode; + checkable: true enabled: true } @@ -429,7 +430,9 @@ ApplicationWindow { } Settings { + id: appSettings property alias gasEstimation: gasEstimationAction.checked property alias optimizeCode: optimizeCodeAction.checked + property string nodeAddress: "http://localhost:8545" } } diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 11cf80b11..7287c2fba 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -19,7 +19,7 @@ function defaultTransaction() function rpcCall(requests, callBack, error) { - var jsonRpcUrl = "http://localhost:8545"; + var jsonRpcUrl = appSettings.nodeAddress; var rpcRequest = JSON.stringify(requests); console.log(rpcRequest); var httpRequest = new XMLHttpRequest(); From 63db8119a03a7a0baac7b92e0e6ce5ea86fb54f0 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 11 Aug 2015 11:24:47 +0200 Subject: [PATCH 07/16] reload we context on scenario run --- mix/qml/WebPreview.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 1b3b1dc40..616bb92a8 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -94,6 +94,11 @@ Item { onContractInterfaceChanged: reload(); } + Connections { + target: clientModel + onRunComplete: reload(); + } + Connections { target: projectModel @@ -313,7 +318,6 @@ Item { width: parent.width Layout.preferredWidth: parent.width id: webView - experimental.settings.localContentCanAccessRemoteUrls: true onJavaScriptConsoleMessage: { console.log(sourceID + ":" + lineNumber + ": " + message); webPreview.javaScriptMessage(level, sourceID, lineNumber - 1, message); From 7d89b9530c8f0167dc86bd74786d6f51c162463f Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 11 Aug 2015 13:23:47 +0200 Subject: [PATCH 08/16] enable debugging of excepted transactions --- mix/ClientModel.cpp | 38 ++++++++++++++++++++++++++++++++++++++ mix/MachineStates.h | 1 + mix/MixClient.cpp | 32 +++----------------------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index de55bebfa..01d1e7528 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -449,6 +449,44 @@ void ClientModel::executeSequence(vector const& _sequence) } m_gasCosts.append(m_client->lastExecution().gasUsed); onNewTransaction(); + TransactionException exception = m_client->lastExecution().excepted; + if (exception != TransactionException::None) + { + switch (m_client->lastExecution().excepted) + { + case TransactionException::None: + break; + case TransactionException::NotEnoughCash: + emit runFailed("Insufficient balance for contract deployment"); + break; + case TransactionException::OutOfGasIntrinsic: + case TransactionException::OutOfGasBase: + case TransactionException::OutOfGas: + emit runFailed("Not enough gas"); + break; + case TransactionException::BlockGasLimitReached: + emit runFailed("Block gas limit reached"); + break; + case TransactionException::BadJumpDestination: + emit runFailed("Solidity exception (bad jump)"); + break; + case TransactionException::OutOfStack: + emit runFailed("Out of stack"); + break; + case TransactionException::StackUnderflow: + emit runFailed("Stack underflow"); + //these should not happen in mix + case TransactionException::Unknown: + case TransactionException::BadInstruction: + case TransactionException::InvalidSignature: + case TransactionException::InvalidNonce: + case TransactionException::InvalidFormat: + case TransactionException::BadRLP: + emit runFailed("Internal execution error"); + break; + } + break; + } } emit runComplete(); } diff --git a/mix/MachineStates.h b/mix/MachineStates.h index 9a9acecf4..bb1c46c1d 100644 --- a/mix/MachineStates.h +++ b/mix/MachineStates.h @@ -85,6 +85,7 @@ struct ExecutionResult unsigned executonIndex = 0; bytes inputParameters; eth::LocalisedLogEntries logs; + eth::TransactionException excepted = eth::TransactionException::Unknown; bool isCall() const { return transactionIndex == std::numeric_limits::max(); } bool isConstructor() const { return !isCall() && !address; } diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 89b749629..2698f259e 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -199,35 +199,8 @@ ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& execution.go(onOp); execution.finalize(); - switch (er.excepted) - { - case TransactionException::None: - break; - case TransactionException::NotEnoughCash: - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment")); - case TransactionException::OutOfGasIntrinsic: - case TransactionException::OutOfGasBase: - case TransactionException::OutOfGas: - BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas")); - case TransactionException::BlockGasLimitReached: - BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Block gas limit reached")); - case TransactionException::BadJumpDestination: - BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Solidity exception (bad jump)")); - case TransactionException::OutOfStack: - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Out of stack")); - case TransactionException::StackUnderflow: - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Stack underflow")); - //these should not happen in mix - case TransactionException::Unknown: - case TransactionException::BadInstruction: - case TransactionException::InvalidSignature: - case TransactionException::InvalidNonce: - case TransactionException::InvalidFormat: - case TransactionException::BadRLP: - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error")); - } - ExecutionResult d; + d.excepted = er.excepted; d.inputParameters = _t.data(); d.result = er; d.machineStates = machineStates; @@ -257,7 +230,8 @@ void MixClient::executeTransaction(Transaction const& _t, Block& _block, bool _c // execute on a state if (!_call) { - t = _gasAuto ? replaceGas(_t, d.gasUsed, _secret) : _t; + u256 useGas = min(d.gasUsed, _block.gasLimitRemaining()); + t = _gasAuto ? replaceGas(_t, useGas, _secret) : _t; eth::ExecutionResult const& er = _block.execute(envInfo.lastHashes(), t); if (t.isCreation() && _block.state().code(d.contractAddress).empty()) BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment")); From c188bf0dfd0bca46f17e84ae379dc1c1b2d280c3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 11 Aug 2015 15:53:49 +0200 Subject: [PATCH 09/16] Properly set default Gas Price in Web3 server Fixes #2767 --- libweb3jsonrpc/WebThreeStubServerBase.cpp | 38 ++++++++--------------- libweb3jsonrpc/WebThreeStubServerBase.h | 1 + 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 193a795a6..21bc9556a 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -239,19 +239,22 @@ string WebThreeStubServerBase::eth_getCode(string const& _address, string const& } } +void WebThreeStubServerBase::setTransactionDefaults(TransactionSkeleton & _t) +{ + if (!_t.from) + _t.from = m_ethAccounts->defaultTransactAccount(); + if (_t.gasPrice == UndefinedU256) + _t.gasPrice = c_defaultGasPrice; + if (_t.gas == UndefinedU256) + _t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(_t.from) / _t.gasPrice); +} + string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json) { try { TransactionSkeleton t = toTransactionSkeleton(_json); - - if (!t.from) - t.from = m_ethAccounts->defaultTransactAccount(); - if (t.gasPrice == UndefinedU256) - t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. - if (t.gas == UndefinedU256) - t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice); - + setTransactionDefaults(t); return toJS(m_ethAccounts->authenticate(t)); } catch (...) @@ -265,14 +268,7 @@ string WebThreeStubServerBase::eth_signTransaction(Json::Value const& _json) try { TransactionSkeleton t = toTransactionSkeleton(_json); - - if (!t.from) - t.from = m_ethAccounts->defaultTransactAccount(); - if (t.gasPrice == UndefinedU256) - t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. - if (t.gas == UndefinedU256) - t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice); - + setTransactionDefaults(t); m_ethAccounts->authenticate(t); return toJS((t.creation ? Transaction(t.value, t.gasPrice, t.gas, t.data) : Transaction(t.value, t.gasPrice, t.gas, t.to, t.data)).sha3(WithoutSignature)); @@ -312,15 +308,7 @@ string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& try { TransactionSkeleton t = toTransactionSkeleton(_json); - if (!t.from) - t.from = m_ethAccounts->defaultTransactAccount(); - // if (!m_accounts->isRealAccount(t.from)) - // return ret; - if (t.gasPrice == UndefinedU256) - t.gasPrice = 10 * dev::eth::szabo; - if (t.gas == UndefinedU256) - t.gas = client()->gasLimitRemaining(); - + setTransactionDefaults(t); return toJS(client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient).output); } catch (...) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index fabb9dde1..8160c6cac 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -193,6 +193,7 @@ public: protected: void requires(std::string const& _session, Privilege _l) const { if (!hasPrivilegeLevel(_session, _l)) throw jsonrpc::JsonRpcException("Invalid privileges"); } + void setTransactionDefaults(eth::TransactionSkeleton & _t); virtual bool hasPrivilegeLevel(std::string const& _session, Privilege _l) const { (void)_session; (void)_l; return false; } virtual dev::eth::Interface* client() = 0; From de90fb6637756f7c8e924630c6d1f696e14b2433 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 11 Aug 2015 16:21:32 +0200 Subject: [PATCH 10/16] better error handling of rpc errors --- mix/ClientModel.cpp | 71 +++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 01d1e7528..7a51c99f7 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -451,42 +451,7 @@ void ClientModel::executeSequence(vector const& _sequence) onNewTransaction(); TransactionException exception = m_client->lastExecution().excepted; if (exception != TransactionException::None) - { - switch (m_client->lastExecution().excepted) - { - case TransactionException::None: - break; - case TransactionException::NotEnoughCash: - emit runFailed("Insufficient balance for contract deployment"); - break; - case TransactionException::OutOfGasIntrinsic: - case TransactionException::OutOfGasBase: - case TransactionException::OutOfGas: - emit runFailed("Not enough gas"); - break; - case TransactionException::BlockGasLimitReached: - emit runFailed("Block gas limit reached"); - break; - case TransactionException::BadJumpDestination: - emit runFailed("Solidity exception (bad jump)"); - break; - case TransactionException::OutOfStack: - emit runFailed("Out of stack"); - break; - case TransactionException::StackUnderflow: - emit runFailed("Stack underflow"); - //these should not happen in mix - case TransactionException::Unknown: - case TransactionException::BadInstruction: - case TransactionException::InvalidSignature: - case TransactionException::InvalidNonce: - case TransactionException::InvalidFormat: - case TransactionException::BadRLP: - emit runFailed("Internal execution error"); - break; - } break; - } } emit runComplete(); } @@ -802,6 +767,42 @@ void ClientModel::onStateReset() void ClientModel::onNewTransaction() { ExecutionResult const& tr = m_client->lastExecution(); + + switch (tr.excepted) + { + case TransactionException::None: + break; + case TransactionException::NotEnoughCash: + emit runFailed("Insufficient balance for contract deployment"); + break; + case TransactionException::OutOfGasIntrinsic: + case TransactionException::OutOfGasBase: + case TransactionException::OutOfGas: + emit runFailed("Not enough gas"); + break; + case TransactionException::BlockGasLimitReached: + emit runFailed("Block gas limit reached"); + break; + case TransactionException::BadJumpDestination: + emit runFailed("Solidity exception (bad jump)"); + break; + case TransactionException::OutOfStack: + emit runFailed("Out of stack"); + break; + case TransactionException::StackUnderflow: + emit runFailed("Stack underflow"); + //these should not happen in mix + case TransactionException::Unknown: + case TransactionException::BadInstruction: + case TransactionException::InvalidSignature: + case TransactionException::InvalidNonce: + case TransactionException::InvalidFormat: + case TransactionException::BadRLP: + emit runFailed("Internal execution error"); + break; + } + + unsigned block = m_client->number() + 1; unsigned recordIndex = tr.executonIndex; QString transactionIndex = tr.isCall() ? QObject::tr("Call") : QString("%1:%2").arg(block).arg(tr.transactionIndex); From e46635f956222f2284465ab05cd3e3b440dda89a Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 11 Aug 2015 19:26:35 +0200 Subject: [PATCH 11/16] AlethZero: Require to confirm all transactions Temporary fix, long-term fix should include the switch plus a warning to users if they disable confirmations. --- alethzero/MainWin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 813c2c745..3de2343d8 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -328,7 +328,7 @@ void Main::noteAddressesChanged() bool Main::confirm() const { - return ui->natSpec->isChecked(); + return true; //ui->natSpec->isChecked(); } void Main::on_gasPrices_triggered() @@ -472,7 +472,7 @@ Address Main::getCurrencies() const bool Main::doConfirm() { - return ui->confirm->isChecked(); + return true; //ui->confirm->isChecked(); } void Main::installNameRegWatch() From 2d2fbe6c7d70e0f5ee00ca72a1ca5b6f72011fe6 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 12 Aug 2015 09:07:00 +0200 Subject: [PATCH 12/16] Add info about logging in the coding standards --- CodingStandards.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CodingStandards.txt b/CodingStandards.txt index a065928d3..76f9920e7 100644 --- a/CodingStandards.txt +++ b/CodingStandards.txt @@ -226,3 +226,15 @@ a. Includes should go in order of lower level (STL -> boost -> libdevcore -> lib #include b. The only exception to the above rule is the top of a .cpp file where its corresponding header should be located. + +13. Logging + +Logging should be performed at appropriate verbosities depending on the logging message. +The more likely a message is to repeat (and thus cuase noise) the higher in verbosity it should be. +Some rules to keep in mind: + + - Verbosity == 0 -> Reserved for important stuff that users must see and can understand. + - Verbosity == 1 -> Reserved for stuff that users don't need to see but can understand. + - Verbosity >= 2 -> Anything that is or might be displayed more than once every minute + - Verbosity >= 3 -> Anything that only a developer would understand + - Verbosity >= 4 -> Anything that is low-level (e.g. peer disconnects, timers being cancelled) From ebccf607d168ebfca0704ad747e3ed60f9132a82 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 12 Aug 2015 09:36:57 +0200 Subject: [PATCH 13/16] eth++ now respects gas price CLI arguments --- libethereum/Client.h | 2 ++ libethereum/ClientBase.h | 1 + libethereum/Interface.h | 2 ++ libweb3jsonrpc/WebThreeStubServerBase.cpp | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libethereum/Client.h b/libethereum/Client.h index 4c5afc652..a7d184d76 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -98,6 +98,8 @@ public: /// Get the remaining gas limit in this block. virtual u256 gasLimitRemaining() const override { return m_postMine.gasLimitRemaining(); } + /// Get the gas bid price + virtual u256 gasBidPrice() const override { return m_gp->bid(); } // [PRIVATE API - only relevant for base clients, not available in general] /// Get the block. diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 6940ace32..8cbc31be2 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -148,6 +148,7 @@ public: using Interface::addresses; virtual Addresses addresses(BlockNumber _block) const override; virtual u256 gasLimitRemaining() const override; + virtual u256 gasBidPrice() const override { return c_defaultGasPrice; } /// Get the coinbase address virtual Address address() const override; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index dff990cbd..ef35d808c 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -190,6 +190,8 @@ public: /// Get the remaining gas limit in this block. virtual u256 gasLimitRemaining() const = 0; + // Get the gas bidding price + virtual u256 gasBidPrice() const = 0; // [MINING API]: diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 21bc9556a..e5d442acb 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -244,7 +244,7 @@ void WebThreeStubServerBase::setTransactionDefaults(TransactionSkeleton & _t) if (!_t.from) _t.from = m_ethAccounts->defaultTransactAccount(); if (_t.gasPrice == UndefinedU256) - _t.gasPrice = c_defaultGasPrice; + _t.gasPrice = client()->gasBidPrice(); if (_t.gas == UndefinedU256) _t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(_t.from) / _t.gasPrice); } From 1a668144041f8c870ed28eb6af551d4113bd0fb8 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 12 Aug 2015 10:26:59 +0200 Subject: [PATCH 14/16] fixed mix build for qt 5.4 --- alethzero/CMakeLists.txt | 2 +- mix/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 1576a016f..64e087230 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -22,7 +22,7 @@ include_directories(${Boost_INCLUDE_DIRS}) find_package (Qt5WebEngine) find_package (Qt5WebEngineWidgets) -if (APPLE) +if (APPLE AND (NOT "${Qt5Core_VERSION_STRING}" VERSION_LESS "5.5")) # TODO: remove indirect dependencies once macdeployqt is fixed find_package (Qt5WebEngineCore) find_package (Qt5DBus) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 91e3d8508..b508ae9c6 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -56,7 +56,7 @@ if (${ETH_HAVE_WEBENGINE}) add_definitions(-DETH_HAVE_WEBENGINE) list(APPEND LIBRARIES "Qt5::WebEngine") endif() -if (APPLE) +if (APPLE AND (NOT "${Qt5Core_VERSION_STRING}" VERSION_LESS "5.5")) list(APPEND LIBRARIES "Qt5::WebEngineCore") list(APPEND LIBRARIES "Qt5::DBus") list(APPEND LIBRARIES "Qt5::PrintSupport") From 7102460fcc40129ca1b90b22cde85cea54bda91b Mon Sep 17 00:00:00 2001 From: etherninja Date: Wed, 12 Aug 2015 04:07:04 -0500 Subject: [PATCH 15/16] update max workgroup size to allow 256 --- libethcore/EthashGPUMiner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethcore/EthashGPUMiner.cpp b/libethcore/EthashGPUMiner.cpp index 5baeec5f0..73c8db61f 100644 --- a/libethcore/EthashGPUMiner.cpp +++ b/libethcore/EthashGPUMiner.cpp @@ -213,7 +213,7 @@ bool EthashGPUMiner::configureGPU( s_platformId = _platformId; s_deviceId = _deviceId; - if (_localWorkSize != 32 && _localWorkSize != 64 && _localWorkSize != 128) + if (_localWorkSize != 32 && _localWorkSize != 64 && _localWorkSize != 128 && _localWorkSize != 256) { cout << "Given localWorkSize of " << toString(_localWorkSize) << "is invalid. Must be either 32,64, or 128" << endl; return false; From d768c198eac12343de70c54f68e7d129e80a7a39 Mon Sep 17 00:00:00 2001 From: etherninja Date: Wed, 12 Aug 2015 04:12:44 -0500 Subject: [PATCH 16/16] Update EthashGPUMiner.cpp --- libethcore/EthashGPUMiner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethcore/EthashGPUMiner.cpp b/libethcore/EthashGPUMiner.cpp index 73c8db61f..de184944f 100644 --- a/libethcore/EthashGPUMiner.cpp +++ b/libethcore/EthashGPUMiner.cpp @@ -215,7 +215,7 @@ bool EthashGPUMiner::configureGPU( if (_localWorkSize != 32 && _localWorkSize != 64 && _localWorkSize != 128 && _localWorkSize != 256) { - cout << "Given localWorkSize of " << toString(_localWorkSize) << "is invalid. Must be either 32,64, or 128" << endl; + cout << "Given localWorkSize of " << toString(_localWorkSize) << "is invalid. Must be either 32,64,128 or 256" << endl; return false; }