From ef7561b16e611d0fbe797ad763380061370183cf Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Jan 2015 14:36:46 +0100 Subject: [PATCH 01/17] - Manage solidity parameter types --- mix/AppContext.cpp | 5 ++ mix/ClientModel.cpp | 21 +++--- mix/ClientModel.h | 2 +- mix/ContractCallDataEncoder.cpp | 115 +++++++++++++++++----------- mix/ContractCallDataEncoder.h | 12 ++- mix/QBigInt.h | 1 + mix/QFunctionDefinition.cpp | 2 + mix/QVariableDeclaration.h | 11 ++- mix/QVariableDefinition.cpp | 130 ++++++++++++++++++++++++++++++++ mix/QVariableDefinition.h | 74 +++++++++++++++++- mix/qml.qrc | 5 ++ mix/qml/QBoolType.qml | 8 ++ mix/qml/QHashType.qml | 8 ++ mix/qml/QIntType.qml | 8 ++ mix/qml/QRealType.qml | 8 ++ mix/qml/QVariableDefinition.qml | 13 ++++ mix/qml/TransactionDialog.qml | 44 +++++++++-- 17 files changed, 399 insertions(+), 68 deletions(-) create mode 100644 mix/qml/QBoolType.qml create mode 100644 mix/qml/QHashType.qml create mode 100644 mix/qml/QIntType.qml create mode 100644 mix/qml/QRealType.qml create mode 100644 mix/qml/QVariableDefinition.qml diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index fb44a1cde..8ffa0f6dd 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -71,6 +71,11 @@ void AppContext::load() m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); qmlRegisterType("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); + //qmlRegisterType("org.ethereum.qml.QVariableDefinition", 1, 0, "QVariableDefinition"); + qmlRegisterType("org.ethereum.qml.QIntType", 1, 0, "QIntType"); + qmlRegisterType("org.ethereum.qml.QRealType", 1, 0, "QRealType"); + qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); + qmlRegisterType("org.ethereum.qml.QHashType", 1, 0, "QHashType"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index eb61c8554..7f9a37aad 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -42,6 +42,10 @@ ClientModel::ClientModel(AppContext* _context): m_context(_context), m_running(false) { qRegisterMetaType("QBigInt*"); + qRegisterMetaType("QIntType*"); + qRegisterMetaType("QStringType*"); + qRegisterMetaType("QRealType*"); + qRegisterMetaType("QHashType*"); qRegisterMetaType("QEther*"); qRegisterMetaType("QVariableDefinition*"); qRegisterMetaType("QVariableDefinitionList*"); @@ -80,8 +84,10 @@ void ClientModel::debugState(QVariantMap _state) TransactionSettings transactionSettings(functionId, value, gas, gasPrice); for (auto p = params.cbegin(); p != params.cend(); ++p) - transactionSettings.parameterValues.insert(std::make_pair(p.key(), (qvariant_cast(p.value()))->toU256Wei())); - + { + QVariableDefinition* param = qvariant_cast(p.value()); + transactionSettings.parameterValues.push_back(param); + } transactionSequence.push_back(transactionSettings); } executeSequence(transactionSequence, balance); @@ -123,15 +129,8 @@ void ClientModel::executeSequence(std::vector const& _seque throw std::runtime_error("function " + t.functionId.toStdString() + " not found"); c.encode(f); - for (int p = 0; p < f->parametersList().size(); p++) - { - QVariableDeclaration* var = (QVariableDeclaration*)f->parametersList().at(p); - u256 value = 0; - auto v = t.parameterValues.find(var->name()); - if (v != t.parameterValues.cend()) - value = v->second; - c.encode(var, value); - } + for (int p = 0; p < t.parameterValues.size(); p++) + c.push(t.parameterValues.at(p)->encodeValue()); transactonData.emplace_back(c.encodedData()); } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 0e7f9c092..5170fcde3 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -54,7 +54,7 @@ struct TransactionSettings /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value - std::map parameterValues; + QList parameterValues; }; diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 7a38db22b..e3dcf9abb 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -44,26 +44,9 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function) m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end()); } -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, bool _value) +void ContractCallDataEncoder::push(bytes _b) { - return encode(_dec, QString(formatBool(_value))); -} - -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, QString _value) -{ - int padding = this->padding(_dec->type()); - bytes data = padded(jsToBytes(_value.toStdString()), padding); - m_encodedData.insert(m_encodedData.end(), data.begin(), data.end()); -} - -void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, u256 _value) -{ - int padding = this->padding(_dec->type()); - std::ostringstream s; - s << std::hex << "0x" << _value; - bytes data = padded(jsToBytes(s.str()), padding); - m_encodedData.insert(m_encodedData.end(), data.begin(), data.end()); - encodedData(); + m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end()); } QList ContractCallDataEncoder::decode(QList _returnParameters, bytes _value) @@ -74,37 +57,79 @@ QList ContractCallDataEncoder::decode(QListpadding(dec->type()); - std::string rawParam = returnValue.substr(0, padding * 2); - r.append(new QVariableDefinition(dec, convertToReadable(unpadLeft(rawParam), dec))); - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + QVariableDefinition* def = nullptr; + if (dec->type().contains("int")) + def = new QIntType(dec, QString()); + else if (dec->type().contains("real")) + def = new QRealType(dec, QString()); + else if (dec->type().contains("string") || dec->type().contains("text")) + def = new QStringType(dec, QString()); + else if (dec->type().contains("hash") || dec->type().contains("address")) + def = new QHashType(dec, QString()); + + def->decodeValue(returnValue); + r.push_back(def); + returnValue = returnValue.substr(def->length(), returnValue.length() - 1); + + /*QStringList tLength = typeLength(dec->type()); + + QRegExp intTest("(uint|int|hash|address)"); + QRegExp stringTest("(string|text)"); + QRegExp realTest("(real|ureal)"); + if (intTest.indexIn(dec->type()) != -1) + { + std::string rawParam = returnValue.substr(0, (tLength.first().toInt() / 8) * 2); + QString value = resolveNumber(QString::fromStdString(rawParam)); + r.append(new QVariableDefinition(dec, value)); + returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + } + else if (dec->type() == "bool") + { + std::string rawParam = returnValue.substr(0, 2); + std::string unpadded = unpadLeft(rawParam); + r.append(new QVariableDefinition(dec, QString::fromStdString(unpadded))); + returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + } + else if (stringTest.indexIn(dec->type()) != -1) + { + if (tLength.length() == 0) + { + QString strLength = QString::fromStdString(returnValue.substr(0, 2)); + returnValue = returnValue.substr(2, returnValue.length() - 1); + QString strValue = QString::fromStdString(returnValue.substr(0, strLength.toInt())); + r.append(new QVariableDefinition(dec, strValue)); + returnValue = returnValue.substr(strValue.length(), returnValue.length() - 1); + } + else + { + std::string rawParam = returnValue.substr(0, (tLength.first().toInt() / 8) * 2); + r.append(new QVariableDefinition(dec, QString::fromStdString(rawParam))); + returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + } + } + else if (realTest.indexIn(dec->type()) != -1) + { + QString value; + for (QString str: tLength) + { + std::string rawParam = returnValue.substr(0, (str.toInt() / 8) * 2); + QString value = resolveNumber(QString::fromStdString(rawParam)); + value += value + "x"; + returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); + } + r.append(new QVariableDefinition(dec, value)); + }*/ } return r; } -int ContractCallDataEncoder::padding(QString type) -{ - // TODO : to be improved (load types automatically from solidity library). - if (type.indexOf("uint") != -1) - return integerPadding(type.remove("uint").toInt()); - else if (type.indexOf("int") != -1) - return integerPadding(type.remove("int").toInt()); - else if (type.indexOf("bool") != -1) - return 1; - else if ((type.indexOf("address") != -1)) - return 32; - else - return 0; -} - -int ContractCallDataEncoder::integerPadding(int bitValue) -{ - return bitValue / 8; -} - -QString ContractCallDataEncoder::formatBool(bool _value) +QString ContractCallDataEncoder::resolveNumber(QString const& _rawParam) { - return (_value ? "1" : "0"); + std::string unPadded = unpadLeft(_rawParam.toStdString()); + int x = std::stol(unPadded, nullptr, 16); + std::stringstream ss; + ss << std::dec << x; + return QString::fromStdString(ss.str()); } QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec) diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index 49410a7cd..f92b25902 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -42,9 +42,9 @@ class ContractCallDataEncoder public: ContractCallDataEncoder() {} /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, QString _value); + void encode(QVariableDeclaration const* _dec, QString _baseType, QStringList _length, QString _value); /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, u256 _value); + void encode(QVariableDeclaration const* _dec, QString _value); /// Encode variable in order to be sent as parameter. void encode(QVariableDeclaration const* _dec, bool _value); /// Encode hash of the function to call. @@ -53,15 +53,21 @@ public: QList decode(QList _dec, bytes _value); /// Get all encoded data encoded by encode function. bytes encodedData(); + /// Encode the given list of parameters (@a _p) + void encode(QVariableDefinition const* _dec); + /// Push the given @ _b to the current stored bytes. + void push(bytes _b); private: - int padding(QString _type); + //int padding(QString _type); bytes m_encodedData; + static bytes encodeNumber(QString _value, QString _length); static QString convertToReadable(std::string _v, QVariableDeclaration* _dec); static QString convertToBool(std::string _v); static QString convertToInt(std::string _v); static int integerPadding(int _bitValue); static QString formatBool(bool _value); + static QString resolveNumber(QString const& _rawParams); }; } diff --git a/mix/QBigInt.h b/mix/QBigInt.h index 842b86c7d..e68b92259 100644 --- a/mix/QBigInt.h +++ b/mix/QBigInt.h @@ -28,6 +28,7 @@ #include #include #include +#include "QVariableDefinition.h" using namespace dev; diff --git a/mix/QFunctionDefinition.cpp b/mix/QFunctionDefinition.cpp index 97ce0ff58..1630ffe83 100644 --- a/mix/QFunctionDefinition.cpp +++ b/mix/QFunctionDefinition.cpp @@ -33,6 +33,8 @@ QFunctionDefinition::QFunctionDefinition(dev::solidity::FunctionDefinition const for (unsigned i = 0; i < parameters.size(); i++) m_parameters.append(new QVariableDeclaration(parameters.at(i).get())); + + std::vector> returnParameters = _f->getReturnParameters(); for (unsigned i = 0; i < returnParameters.size(); i++) m_returnParameters.append(new QVariableDeclaration(returnParameters.at(i).get())); diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index 966ee0ff3..78f97994f 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include #include "QBasicNodeDefinition.h" @@ -37,7 +38,15 @@ class QVariableDeclaration: public QBasicNodeDefinition public: QVariableDeclaration() {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} - QString type() const { return m_type; } + Q_INVOKABLE QString type() const { return m_type; } + QStringList typeLength() + { + QRegExp rules("\\d"); + int pos = 0; + while ((pos = rules.indexIn(m_type, pos)) != -1) {} + return rules.capturedTexts(); + } + private: QString m_type; }; diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index 4f38e84b2..3ac036222 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include "QVariableDefinition.h" using namespace dev::mix; @@ -53,3 +54,132 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx) return nullptr; return m_def.at(_idx); } + +/* + * QIntType + */ +dev::bytes QIntType::encodeValue() +{ + std::ostringstream s; + s << std::hex << "0x" << value().toStdString(); + return padded(jsToBytes(s.str()), declaration()->typeLength().first().toInt() / 8); +} + +int QIntType::length() +{ + return (declaration()->typeLength().first().toInt() / 8) * 2; +} + +void QIntType::decodeValue(std::string const& _rawValue) +{ + std::string unPadded = unpadLeft(_rawValue); + int x = std::stol(unPadded, nullptr, 16); + std::stringstream ss; + ss << std::dec << x; + setValue(QString::fromStdString(ss.str())); +} + +/* + * QHashType + */ +dev::bytes QHashType::encodeValue() +{ + return bytes(); +} + +int QHashType::length() +{ + return (declaration()->typeLength().first().toInt() / 8) * 2; +} + +void QHashType::decodeValue(std::string const& _rawValue) +{ + Q_UNUSED(_rawValue); +} + +/* + * QRealType + */ +dev::bytes QRealType::encodeValue() +{ + + std::ostringstream s; + s << std::hex << "0x" << value().split("x").first().toStdString(); + bytes first = padded(jsToBytes(s.str()), declaration()->typeLength().first().toInt() / 8); + s << std::hex << "0x" << value().split("x").last().toStdString(); + bytes second = padded(jsToBytes(s.str()), declaration()->typeLength().last().toInt() / 8); + first.insert(first.end(), second.begin(), second.end()); + return first; +} + +int QRealType::length() +{ + return (declaration()->typeLength().first().toInt() / 8) * 2 + (declaration()->typeLength().last().toInt() / 8) * 2; +} + +void QRealType::decodeValue(std::string const& _rawValue) +{ + QString value; + for (QString str: declaration()->typeLength()) + { + std::string rawParam = _rawValue.substr(0, (str.toInt() / 8) * 2); + std::string unPadded = unpadLeft(rawParam); + int x = std::stol(unPadded, nullptr, 16); + std::stringstream ss; + ss << std::dec << x; + value += QString::fromStdString(ss.str()) + "x"; + } + setValue(value); +} + +/* + * QStringType + */ +dev::bytes QStringType::encodeValue() +{ + return padded(jsToBytes(value().toStdString()), declaration()->typeLength().first().toInt() / 8); +} + +int QStringType::length() +{ + if (declaration()->typeLength().length() == 0) + return value().length() + 2; + else + return (declaration()->typeLength().first().toInt() / 8) * 2; +} + +void QStringType::decodeValue(std::string const& _rawValue) +{ + if (declaration()->typeLength().first().length() == 0) + { + std::string strLength = _rawValue.substr(0, 2); + std::string strValue = _rawValue.substr(2, std::stoi(strLength)); + setValue(QString::fromStdString(strValue)); + } + else + { + std::string rawParam = _rawValue.substr(0, (declaration()->typeLength().first().toInt() / 8) * 2); + setValue(QString::fromStdString(rawParam)); + } +} + +/* + * QBoolType + */ +dev::bytes QBoolType::encodeValue() +{ + return padded(jsToBytes(value().toStdString()), 1); +} + +int QBoolType::length() +{ + return 1; +} + +void QBoolType::decodeValue(std::string const& _rawValue) +{ + std::string rawParam = _rawValue.substr(0, 2); + std::string unpadded = unpadLeft(rawParam); + setValue(QString::fromStdString(unpadded)); +} + diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index f55e51346..6f90e1da5 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -37,12 +37,18 @@ class QVariableDefinition: public QObject Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT) public: + QVariableDefinition() {} QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {} /// Return the associated declaration of this variable definition. - QVariableDeclaration* declaration() const { return m_dec; } + Q_INVOKABLE QVariableDeclaration* declaration() const { return m_dec; } /// Return the variable value. QString value() const { return m_value; } + Q_INVOKABLE void setValue(QString _value) { m_value = _value; } + Q_INVOKABLE void setDeclaration(QVariableDeclaration* _dec) { m_dec = _dec; } + virtual bytes encodeValue() = 0; + virtual void decodeValue(std::string const& _rawValue) = 0; + virtual int length() = 0; private: QString m_value; @@ -67,7 +73,71 @@ private: QList m_def; }; +class QIntType: public QVariableDefinition +{ + Q_OBJECT + +public: + QIntType() {} + QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(std::string const& _rawValue) override; + int length() override; +}; + +class QRealType: public QVariableDefinition +{ + Q_OBJECT + +public: + QRealType() {} + QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(std::string const& _rawValue) override; + int length() override; +}; + +class QStringType: public QVariableDefinition +{ + Q_OBJECT + +public: + QStringType() {} + QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(std::string const& _rawValue) override; + int length() override; +}; + +class QHashType: public QVariableDefinition +{ + Q_OBJECT + +public: + QHashType() {} + QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(std::string const& _rawValue) override; + int length() override; +}; + +class QBoolType: public QVariableDefinition +{ + Q_OBJECT + +public: + QBoolType() {} + QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + dev::bytes encodeValue() override; + void decodeValue(std::string const& _rawValue) override; + int length() override; +}; + } } -Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*) +//Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*) +Q_DECLARE_METATYPE(dev::mix::QIntType*) +Q_DECLARE_METATYPE(dev::mix::QStringType*) +Q_DECLARE_METATYPE(dev::mix::QHashType*) +Q_DECLARE_METATYPE(dev::mix::QBoolType*) diff --git a/mix/qml.qrc b/mix/qml.qrc index 169d1ebcb..fecea2e2c 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -43,5 +43,10 @@ qml/Ether.qml qml/EtherValue.qml qml/BigIntValue.qml + qml/QVariableDefinition.qml + qml/QBoolType.qml + qml/QHashType.qml + qml/QIntType.qml + qml/QRealType.qml diff --git a/mix/qml/QBoolType.qml b/mix/qml/QBoolType.qml new file mode 100644 index 000000000..a6dc54035 --- /dev/null +++ b/mix/qml/QBoolType.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import org.ethereum.qml.QBoolType 1.0 + +QBoolType +{ + property string view: "qrc:/qml/QBoolTypeView.qml" +} + diff --git a/mix/qml/QHashType.qml b/mix/qml/QHashType.qml new file mode 100644 index 000000000..a7913d414 --- /dev/null +++ b/mix/qml/QHashType.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import org.ethereum.qml.QHashType 1.0 + +QHashType +{ + property string view: "qrc:/qml/QHashTypeView.qml" +} + diff --git a/mix/qml/QIntType.qml b/mix/qml/QIntType.qml new file mode 100644 index 000000000..7533d367f --- /dev/null +++ b/mix/qml/QIntType.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import org.ethereum.qml.QIntType 1.0 + +QIntType +{ + property string view: "qrc:/qml/QIntTypeView.qml" +} + diff --git a/mix/qml/QRealType.qml b/mix/qml/QRealType.qml new file mode 100644 index 000000000..ba3cf82bf --- /dev/null +++ b/mix/qml/QRealType.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import org.ethereum.qml.QRealType 1.0 + +QRealType +{ + property string view: "qrc:/qml/QRealTypeView.qml" +} + diff --git a/mix/qml/QVariableDefinition.qml b/mix/qml/QVariableDefinition.qml new file mode 100644 index 000000000..af0cd4ea0 --- /dev/null +++ b/mix/qml/QVariableDefinition.qml @@ -0,0 +1,13 @@ +/* + * Used to instanciate a QVariableDefinition obj using Qt.createComponent function. +*/ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.1 +import org.ethereum.qml.QVariableDefinition 1.0 + +QVariableDefinition +{ + id: qVariableDefinition +} diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 22995d66b..eb9fd5914 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -28,6 +28,8 @@ Window { valueField.value = item.value; var functionId = item.functionId; itemParams = item.parameters !== undefined ? item.parameters : {}; + console.log("opening ..."); + console.log(JSON.stringify(itemParams)); functionsModel.clear(); var functionIndex = -1; var functions = codeModel.code.contract.functions; @@ -41,21 +43,48 @@ Window { functionIndex = 0; //@todo suggest unused funtion functionComboBox.currentIndex = functionIndex; + console.log("opening2 ..."); + console.log(JSON.stringify(itemParams)); loadParameters(); visible = true; valueField.focus = true; } function loadParameters() { + console.log("opening3 ..."); + console.log(JSON.stringify(itemParams)); if (!paramsModel) return; + console.log("opening4 ..."); + console.log(JSON.stringify(itemParams)); paramsModel.clear(); + console.log("opening5 ..."); + console.log(JSON.stringify(itemParams)); if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { var func = codeModel.code.contract.functions[functionComboBox.currentIndex]; var parameters = func.parameters; for (var p = 0; p < parameters.length; p++) { var pname = parameters[p].name; - paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" }); + var varComponent; + var type = parameters[p].type; + console.log("type : " + type); + console.log("name : " + pname); + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + var param = varComponent.createObject(modalTransactionDialog); + var value = itemParams[pname] !== undefined ? itemParams[pname].value : ""; + + console.log("loading parameters"); + console.log(JSON.stringify(itemParams)); + param.setValue(value); + param.setDeclaration(parameters[p]); + paramsModel.append({ internalValue: param, name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value : "" }); } } } @@ -76,11 +105,16 @@ Window { } for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); - var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); - var param = intComponent.createObject(modalTransactionDialog); - param.setValue(parameter.value); - item.parameters[parameter.name] = param; + //var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); + //var param = intComponent.createObject(modalTransactionDialog); + //param.setValue(parameter.value); + //parameter.internalValue.setValue(parameter.value); + console.log("onget"); + console.log(JSON.stringify(parameter)); + item.parameters[parameter.name] = parameter; } + console.log("return item"); + console.log(JSON.stringify(item)); return item; } From b271a9df51ddb520ee05fcd60dce11ddbe38ff86 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 29 Jan 2015 17:54:58 +0100 Subject: [PATCH 02/17] Manage solidity types: - uint, uint - int, int - hash, hash, address - bool - string --- libdevcore/CommonJS.cpp | 19 +++++ libdevcore/CommonJS.h | 4 + mix/AppContext.cpp | 1 + mix/ClientModel.cpp | 12 ++- mix/CodeHighlighter.cpp | 25 +++--- mix/ContractCallDataEncoder.cpp | 89 ++------------------- mix/ContractCallDataEncoder.h | 18 +---- mix/QBigInt.h | 2 +- mix/QFunctionDefinition.cpp | 2 - mix/QVariableDeclaration.h | 8 +- mix/QVariableDefinition.cpp | 105 +++++++++--------------- mix/QVariableDefinition.h | 10 +-- mix/qml.qrc | 8 +- mix/qml/QBoolTypeView.qml | 30 +++++++ mix/qml/QHashTypeView.qml | 22 ++++++ mix/qml/QIntTypeView.qml | 25 ++++++ mix/qml/QRealTypeView.qml | 15 ++++ mix/qml/QStringType.qml | 8 ++ mix/qml/QStringTypeView.qml | 25 ++++++ mix/qml/StateList.qml | 1 - mix/qml/TransactionDialog.qml | 136 ++++++++++++++++++++++++-------- 21 files changed, 327 insertions(+), 238 deletions(-) create mode 100644 mix/qml/QBoolTypeView.qml create mode 100644 mix/qml/QHashTypeView.qml create mode 100644 mix/qml/QIntTypeView.qml create mode 100644 mix/qml/QRealTypeView.qml create mode 100644 mix/qml/QStringType.qml create mode 100644 mix/qml/QStringTypeView.qml diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index ee2074cd1..1a49d71ec 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -45,6 +45,13 @@ bytes padded(bytes _b, unsigned _l) return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); } +bytes paddedRight(bytes _b, unsigned _l) +{ + while (_b.size() < _l) + _b.insert(_b.end(), 0); + return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); +} + bytes unpadded(bytes _b) { auto p = asString(_b).find_last_not_of((char)0); @@ -52,6 +59,18 @@ bytes unpadded(bytes _b) return _b; } +std::string unpadRight(std::string _b) +{ + while (true) + { + auto p = _b.find_last_of("0"); + if (p == _b.size() - 1) + _b = _b.substr(0, _b.size() - 1); + else + return _b; + } +} + std::string unpadLeft(std::string _b) { auto p = _b.find_first_not_of('0'); diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 8e6c5fe53..4f7ef8495 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -50,6 +50,10 @@ inline std::string toJS(dev::bytes const& _n) bytes jsToBytes(std::string const& _s); /// Add '0' on the head of _b until _l. bytes padded(bytes _b, unsigned _l); +/// Add '0' on the queue of _b until _l. +bytes paddedRight(bytes _b, unsigned _l); +/// Remove all trailing '0' +std::string unpadRight(std::string _b); /// Removing all trailing '0'. Returns empty array if input contains only '0' char. bytes unpadded(bytes _s); /// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'. diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index e35bb8a5d..49cf64c56 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -66,6 +66,7 @@ void AppContext::load() qmlRegisterType("org.ethereum.qml.QRealType", 1, 0, "QRealType"); qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); qmlRegisterType("org.ethereum.qml.QHashType", 1, 0, "QHashType"); + qmlRegisterType("org.ethereum.qml.QBoolType", 1, 0, "QBoolType"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 694561479..df489403b 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -119,12 +119,11 @@ void ClientModel::debugState(QVariantMap _state) u256 gas = (qvariant_cast(transaction.value("gas")))->toU256Wei(); u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); - QVariantMap params = transaction.value("parameters").toMap(); TransactionSettings transactionSettings(functionId, value, gas, gasPrice); - - for (auto p = params.cbegin(); p != params.cend(); ++p) + QVariantList qParams = transaction.value("qType").toList(); + for (QVariant const& variant: qParams) { - QVariableDefinition* param = qvariant_cast(p.value()); + QVariableDefinition* param = qvariant_cast(variant); transactionSettings.parameterValues.push_back(param); } @@ -173,7 +172,12 @@ void ClientModel::executeSequence(std::vector const& _seque c.encode(f); for (int p = 0; p < t.parameterValues.size(); p++) + { + qDebug() << " encode input parameters : " + t.parameterValues.at(p)->declaration()->type(); + qDebug() << t.parameterValues.at(p)->declaration()->type(); + qDebug() << t.parameterValues.at(p)->value(); c.push(t.parameterValues.at(p)->encodeValue()); + } transactonData.emplace_back(c.encodedData()); } diff --git a/mix/CodeHighlighter.cpp b/mix/CodeHighlighter.cpp index ab8a61ff5..c1ef39d5d 100644 --- a/mix/CodeHighlighter.cpp +++ b/mix/CodeHighlighter.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file CodeHighlighter.cpp * @author Arkadiy Paronyan arkadiy@ethdev.com @@ -102,7 +102,8 @@ void CodeHighlighter::processAST(dev::solidity::ASTNode const& _ast) void CodeHighlighter::processError(dev::Exception const& _exception) { Location const* location = boost::get_error_info(_exception); - m_formats.push_back(FormatRange(CodeHighlighterSettings::CompilationError, *location)); + if (location) + m_formats.push_back(FormatRange(CodeHighlighterSettings::CompilationError, *location)); } void CodeHighlighter::processComments(std::string const& _source) diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index e3dcf9abb..4438c9387 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -35,6 +35,7 @@ using namespace dev::mix; bytes ContractCallDataEncoder::encodedData() { + qDebug() << " encoded data " << QString::fromStdString(toJS(m_encodedData)); return m_encodedData; } @@ -62,96 +63,16 @@ QList ContractCallDataEncoder::decode(QListtype().contains("real")) def = new QRealType(dec, QString()); + else if (dec->type().contains("bool")) + def = new QBoolType(dec, QString()); else if (dec->type().contains("string") || dec->type().contains("text")) def = new QStringType(dec, QString()); else if (dec->type().contains("hash") || dec->type().contains("address")) def = new QHashType(dec, QString()); - def->decodeValue(returnValue); r.push_back(def); - returnValue = returnValue.substr(def->length(), returnValue.length() - 1); - - /*QStringList tLength = typeLength(dec->type()); - - QRegExp intTest("(uint|int|hash|address)"); - QRegExp stringTest("(string|text)"); - QRegExp realTest("(real|ureal)"); - if (intTest.indexIn(dec->type()) != -1) - { - std::string rawParam = returnValue.substr(0, (tLength.first().toInt() / 8) * 2); - QString value = resolveNumber(QString::fromStdString(rawParam)); - r.append(new QVariableDefinition(dec, value)); - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); - } - else if (dec->type() == "bool") - { - std::string rawParam = returnValue.substr(0, 2); - std::string unpadded = unpadLeft(rawParam); - r.append(new QVariableDefinition(dec, QString::fromStdString(unpadded))); - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); - } - else if (stringTest.indexIn(dec->type()) != -1) - { - if (tLength.length() == 0) - { - QString strLength = QString::fromStdString(returnValue.substr(0, 2)); - returnValue = returnValue.substr(2, returnValue.length() - 1); - QString strValue = QString::fromStdString(returnValue.substr(0, strLength.toInt())); - r.append(new QVariableDefinition(dec, strValue)); - returnValue = returnValue.substr(strValue.length(), returnValue.length() - 1); - } - else - { - std::string rawParam = returnValue.substr(0, (tLength.first().toInt() / 8) * 2); - r.append(new QVariableDefinition(dec, QString::fromStdString(rawParam))); - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); - } - } - else if (realTest.indexIn(dec->type()) != -1) - { - QString value; - for (QString str: tLength) - { - std::string rawParam = returnValue.substr(0, (str.toInt() / 8) * 2); - QString value = resolveNumber(QString::fromStdString(rawParam)); - value += value + "x"; - returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); - } - r.append(new QVariableDefinition(dec, value)); - }*/ + returnValue = returnValue.substr(32 * 2, returnValue.length() - 1); + qDebug() << "decoded return value : " << dec->type() << " " << def->value(); } return r; } - -QString ContractCallDataEncoder::resolveNumber(QString const& _rawParam) -{ - std::string unPadded = unpadLeft(_rawParam.toStdString()); - int x = std::stol(unPadded, nullptr, 16); - std::stringstream ss; - ss << std::dec << x; - return QString::fromStdString(ss.str()); -} - -QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec) -{ - if (_dec->type().indexOf("int") != -1) - return convertToInt(_v); - else if (_dec->type().indexOf("bool") != -1) - return convertToBool(_v); - else - return QString::fromStdString(_v); -} - -QString ContractCallDataEncoder::convertToBool(std::string _v) -{ - return _v == "1" ? "true" : "false"; -} - -QString ContractCallDataEncoder::convertToInt(std::string _v) -{ - //TO DO to be improve to manage all int, uint size (128, 256, ...) in ethereum QML types task #612. - int x = std::stol(_v, nullptr, 16); - std::stringstream ss; - ss << std::dec << x; - return QString::fromStdString(ss.str()); -} diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index f92b25902..27baef8ee 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -41,33 +41,17 @@ class ContractCallDataEncoder { public: ContractCallDataEncoder() {} - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, QString _baseType, QStringList _length, QString _value); - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, QString _value); - /// Encode variable in order to be sent as parameter. - void encode(QVariableDeclaration const* _dec, bool _value); /// Encode hash of the function to call. void encode(QFunctionDefinition const* _function); /// Decode variable in order to be sent to QML view. QList decode(QList _dec, bytes _value); /// Get all encoded data encoded by encode function. bytes encodedData(); - /// Encode the given list of parameters (@a _p) - void encode(QVariableDefinition const* _dec); - /// Push the given @ _b to the current stored bytes. + /// Push the given @ _b to the current param context. void push(bytes _b); private: - //int padding(QString _type); bytes m_encodedData; - static bytes encodeNumber(QString _value, QString _length); - static QString convertToReadable(std::string _v, QVariableDeclaration* _dec); - static QString convertToBool(std::string _v); - static QString convertToInt(std::string _v); - static int integerPadding(int _bitValue); - static QString formatBool(bool _value); - static QString resolveNumber(QString const& _rawParams); }; } diff --git a/mix/QBigInt.h b/mix/QBigInt.h index e68b92259..0f5c88c43 100644 --- a/mix/QBigInt.h +++ b/mix/QBigInt.h @@ -28,7 +28,6 @@ #include #include #include -#include "QVariableDefinition.h" using namespace dev; @@ -76,6 +75,7 @@ public: QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){ QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } + QBigInt(QString const& _value, QObject* _parent = 0): QObject(_parent) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); setValue(_value); } ~QBigInt() {} /// @returns the current used big integer. diff --git a/mix/QFunctionDefinition.cpp b/mix/QFunctionDefinition.cpp index 1630ffe83..97ce0ff58 100644 --- a/mix/QFunctionDefinition.cpp +++ b/mix/QFunctionDefinition.cpp @@ -33,8 +33,6 @@ QFunctionDefinition::QFunctionDefinition(dev::solidity::FunctionDefinition const for (unsigned i = 0; i < parameters.size(); i++) m_parameters.append(new QVariableDeclaration(parameters.at(i).get())); - - std::vector> returnParameters = _f->getReturnParameters(); for (unsigned i = 0; i < returnParameters.size(); i++) m_returnParameters.append(new QVariableDeclaration(returnParameters.at(i).get())); diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index 78f97994f..08af30798 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include #include #include "QBasicNodeDefinition.h" @@ -39,13 +40,6 @@ public: QVariableDeclaration() {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} Q_INVOKABLE QString type() const { return m_type; } - QStringList typeLength() - { - QRegExp rules("\\d"); - int pos = 0; - while ((pos = rules.indexIn(m_type, pos)) != -1) {} - return rules.capturedTexts(); - } private: QString m_type; diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index 3ac036222..4e29a3a2e 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include #include "QVariableDefinition.h" @@ -60,23 +61,25 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx) */ dev::bytes QIntType::encodeValue() { + dev::bigint i(value().toStdString()); + if (i < 0) + i = i + dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + 1; std::ostringstream s; - s << std::hex << "0x" << value().toStdString(); - return padded(jsToBytes(s.str()), declaration()->typeLength().first().toInt() / 8); -} - -int QIntType::length() -{ - return (declaration()->typeLength().first().toInt() / 8) * 2; + s << std::hex << "0x" << i; + qDebug() << " int input " << QString::fromStdString(toJS(padded(jsToBytes(s.str()), 32))); + return padded(jsToBytes(s.str()), 32); } void QIntType::decodeValue(std::string const& _rawValue) { - std::string unPadded = unpadLeft(_rawValue); - int x = std::stol(unPadded, nullptr, 16); - std::stringstream ss; - ss << std::dec << x; - setValue(QString::fromStdString(ss.str())); + std::string rawParam = _rawValue.substr(0, 32 * 2); + dev::bigint bigint = dev::bigint("0x" + rawParam); + if (((bigint >> 32) & 1) == 1) + bigint = bigint - dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - 1; + std::ostringstream s; + s << std::dec << bigint; + qDebug() << " int output " << QString::fromStdString(s.str()); + setValue(QString::fromStdString(s.str())); } /* @@ -84,17 +87,14 @@ void QIntType::decodeValue(std::string const& _rawValue) */ dev::bytes QHashType::encodeValue() { - return bytes(); -} - -int QHashType::length() -{ - return (declaration()->typeLength().first().toInt() / 8) * 2; + return padded(asBytes(value().toStdString()), 32); } void QHashType::decodeValue(std::string const& _rawValue) { - Q_UNUSED(_rawValue); + std::string rawParam = _rawValue.substr(0, 32 * 2); + std::string unPadded = unpadLeft(rawParam); + setValue(QString::fromStdString(unPadded)); } /* @@ -102,34 +102,12 @@ void QHashType::decodeValue(std::string const& _rawValue) */ dev::bytes QRealType::encodeValue() { - - std::ostringstream s; - s << std::hex << "0x" << value().split("x").first().toStdString(); - bytes first = padded(jsToBytes(s.str()), declaration()->typeLength().first().toInt() / 8); - s << std::hex << "0x" << value().split("x").last().toStdString(); - bytes second = padded(jsToBytes(s.str()), declaration()->typeLength().last().toInt() / 8); - first.insert(first.end(), second.begin(), second.end()); - return first; -} - -int QRealType::length() -{ - return (declaration()->typeLength().first().toInt() / 8) * 2 + (declaration()->typeLength().last().toInt() / 8) * 2; + return bytes(); } void QRealType::decodeValue(std::string const& _rawValue) { - QString value; - for (QString str: declaration()->typeLength()) - { - std::string rawParam = _rawValue.substr(0, (str.toInt() / 8) * 2); - std::string unPadded = unpadLeft(rawParam); - int x = std::stol(unPadded, nullptr, 16); - std::stringstream ss; - ss << std::dec << x; - value += QString::fromStdString(ss.str()) + "x"; - } - setValue(value); + Q_UNUSED(_rawValue); } /* @@ -137,30 +115,24 @@ void QRealType::decodeValue(std::string const& _rawValue) */ dev::bytes QStringType::encodeValue() { - return padded(jsToBytes(value().toStdString()), declaration()->typeLength().first().toInt() / 8); -} - -int QStringType::length() -{ - if (declaration()->typeLength().length() == 0) - return value().length() + 2; - else - return (declaration()->typeLength().first().toInt() / 8) * 2; + qDebug() << QString::fromStdString(toJS(paddedRight(asBytes(value().toStdString()), 32))); + return paddedRight(asBytes(value().toStdString()), 32); } void QStringType::decodeValue(std::string const& _rawValue) { - if (declaration()->typeLength().first().length() == 0) + std::string rawParam = _rawValue.substr(0, 32 * 2); + rawParam = unpadRight(rawParam); + std::string res; + res.reserve(rawParam.size() / 2); + for (unsigned int i = 0; i < rawParam.size(); i += 2) { - std::string strLength = _rawValue.substr(0, 2); - std::string strValue = _rawValue.substr(2, std::stoi(strLength)); - setValue(QString::fromStdString(strValue)); - } - else - { - std::string rawParam = _rawValue.substr(0, (declaration()->typeLength().first().toInt() / 8) * 2); - setValue(QString::fromStdString(rawParam)); + std::istringstream iss(rawParam.substr(i, 2)); + int temp; + iss >> std::hex >> temp; + res += static_cast(temp); } + setValue(QString::fromStdString(res)); } /* @@ -168,18 +140,13 @@ void QStringType::decodeValue(std::string const& _rawValue) */ dev::bytes QBoolType::encodeValue() { - return padded(jsToBytes(value().toStdString()), 1); -} - -int QBoolType::length() -{ - return 1; + qDebug() << QString::fromStdString(toJS(padded(jsToBytes(value().toStdString()), 32))); + return padded(jsToBytes(value().toStdString()), 32); } void QBoolType::decodeValue(std::string const& _rawValue) { - std::string rawParam = _rawValue.substr(0, 2); + std::string rawParam = _rawValue.substr(0, 32 * 2); std::string unpadded = unpadLeft(rawParam); setValue(QString::fromStdString(unpadded)); } - diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index 6f90e1da5..e58cc81f5 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -22,6 +22,7 @@ #pragma once #include +#include "QBigInt.h" #include "QVariableDeclaration.h" namespace dev @@ -48,7 +49,6 @@ public: Q_INVOKABLE void setDeclaration(QVariableDeclaration* _dec) { m_dec = _dec; } virtual bytes encodeValue() = 0; virtual void decodeValue(std::string const& _rawValue) = 0; - virtual int length() = 0; private: QString m_value; @@ -82,7 +82,7 @@ public: QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; - int length() override; + QBigInt* toBigInt() { return new QBigInt(value()); } }; class QRealType: public QVariableDefinition @@ -94,7 +94,6 @@ public: QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; - int length() override; }; class QStringType: public QVariableDefinition @@ -106,7 +105,6 @@ public: QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; - int length() override; }; class QHashType: public QVariableDefinition @@ -118,7 +116,6 @@ public: QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; - int length() override; }; class QBoolType: public QVariableDefinition @@ -130,13 +127,12 @@ public: QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; - int length() override; + bool toBool() { return value() != "0"; } }; } } -//Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*) Q_DECLARE_METATYPE(dev::mix::QIntType*) Q_DECLARE_METATYPE(dev::mix::QStringType*) Q_DECLARE_METATYPE(dev::mix::QHashType*) diff --git a/mix/qml.qrc b/mix/qml.qrc index 730109c4a..558da9d45 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -41,7 +41,7 @@ qml/Ether.qml qml/EtherValue.qml qml/BigIntValue.qml - qml/QVariableDefinition.qml + qml/QVariableDefinition.qml qml/QBoolType.qml qml/QHashType.qml qml/QIntType.qml @@ -49,5 +49,11 @@ qml/js/QEtherHelper.js qml/js/TransactionHelper.js qml/Splitter.qml + qml/QStringType.qml + qml/QBoolTypeView.qml + qml/QIntTypeView.qml + qml/QRealTypeView.qml + qml/QStringTypeView.qml + qml/QHashTypeView.qml diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml new file mode 100644 index 000000000..b71ec9cf4 --- /dev/null +++ b/mix/qml/QBoolTypeView.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.3 + +Item +{ + id: editRoot + property string text + Rectangle { + anchors.fill: parent + ComboBox + { + id: boolCombo + anchors.fill: parent + onCurrentIndexChanged: + { + text = coolComboModel.get(currentIndex).value; + editRoot.textChanged(); + } + model: ListModel + { + id: coolComboModel + ListElement { text: qsTr("True"); value: "1" } + ListElement { text: qsTr("False"); value: "0" } + } + } + } +} + + + diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml new file mode 100644 index 000000000..3e09ca112 --- /dev/null +++ b/mix/qml/QHashTypeView.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + onTextChanged: editRoot.textChanged() + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml new file mode 100644 index 000000000..d9156bf19 --- /dev/null +++ b/mix/qml/QIntTypeView.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + onTextChanged: editRoot.textChanged() + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} + + + diff --git a/mix/qml/QRealTypeView.qml b/mix/qml/QRealTypeView.qml new file mode 100644 index 000000000..96db4de75 --- /dev/null +++ b/mix/qml/QRealTypeView.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Component +{ + Rectangle { + anchors.fill: parent + Text{ + anchors.fill: parent + text: qsTr("Real") + } + } +} + + + diff --git a/mix/qml/QStringType.qml b/mix/qml/QStringType.qml new file mode 100644 index 000000000..ab8db4a42 --- /dev/null +++ b/mix/qml/QStringType.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import org.ethereum.qml.QStringType 1.0 + +QStringType +{ + property string view: "qrc:/qml/QStringTypeView.qml" +} + diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml new file mode 100644 index 000000000..d9156bf19 --- /dev/null +++ b/mix/qml/QStringTypeView.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item +{ + property alias text: textinput.text + id: editRoot + Rectangle { + anchors.fill: parent + TextInput { + id: textinput + text: text + anchors.fill: parent + onTextChanged: editRoot.textChanged() + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } + } + } +} + + + diff --git a/mix/qml/StateList.qml b/mix/qml/StateList.qml index 007a45d6a..c2722f69c 100644 --- a/mix/qml/StateList.qml +++ b/mix/qml/StateList.qml @@ -59,7 +59,6 @@ Rectangle { stateList.push(item); stateListModel.append(item); } - stateListModel.save(); } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index b1244ee0e..a98444b85 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -21,10 +21,12 @@ Window { property var itemParams; property bool isConstructorTransaction; property bool useTransactionDefaultValue: false + property var qType; signal accepted; function open(index, item) { + qType = []; rowFunction.visible = !useTransactionDefaultValue; rowValue.visible = !useTransactionDefaultValue; rowGas.visible = !useTransactionDefaultValue; @@ -39,8 +41,8 @@ Window { rowFunction.visible = !item.executeConstructor; itemParams = item.parameters !== undefined ? item.parameters : {}; - console.log("opening ..."); - console.log(JSON.stringify(itemParams)); + console.log("save parameters : "); + console.log(JSON.stringify(item.qType)); functionsModel.clear(); var functionIndex = -1; var functions = codeModel.code.contract.functions; @@ -70,8 +72,6 @@ Window { } function loadParameters() { - console.log("opening3 ..."); - console.log(JSON.stringify(itemParams)); if (!paramsModel) return; if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { @@ -81,8 +81,7 @@ Window { var pname = parameters[p].name; var varComponent; var type = parameters[p].type; - console.log("type : " + type); - console.log("name : " + pname); + if (type.indexOf("int") !== -1) varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); else if (type.indexOf("real") !== -1) @@ -91,14 +90,16 @@ Window { varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + var param = varComponent.createObject(modalTransactionDialog); - var value = itemParams[pname] !== undefined ? itemParams[pname].value : ""; + var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; - console.log("loading parameters"); - console.log(JSON.stringify(itemParams)); param.setValue(value); param.setDeclaration(parameters[p]); - paramsModel.append({ internalValue: param, name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value : "" }); + qType.push({ name: pname, value: param }); + paramsModel.append({ name: pname, type: parameters[p].type, value: value }); } } } @@ -108,6 +109,15 @@ Window { visible = false; } + function getqTypeParam(name) + { + for (var k in qType) + { + if (qType[k].name === name) + return qType[k].value; + } + } + function getItem() { var item; @@ -132,18 +142,15 @@ Window { if (isConstructorTransaction) item.functionId = qsTr("Constructor"); + var orderedQType = []; for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); - //var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); - //var param = intComponent.createObject(modalTransactionDialog); - //param.setValue(parameter.value); - //parameter.internalValue.setValue(parameter.value); - console.log("onget"); - console.log(JSON.stringify(parameter)); - item.parameters[parameter.name] = parameter; + getqTypeParam(parameter.name).setValue(parameter.value); + orderedQType.push(getqTypeParam(parameter.name)); + item.parameters[parameter.name] = parameter.value; } - console.log("return item"); - console.log(JSON.stringify(item)); + console.log(JSON.stringify(qType)); + item.qType = orderedQType; return item; } @@ -247,7 +254,6 @@ Window { TableView { model: paramsModel Layout.fillWidth: true - TableViewColumn { role: "name" title: "Name" @@ -264,7 +270,13 @@ Window { width: 120 } - itemDelegate: { + rowDelegate: + { + return rowDelegate + } + + itemDelegate: + { return editableDelegate; } } @@ -295,19 +307,15 @@ Window { } Component { - id: editableDelegate + id: rowDelegate Item { + height: 100 + } + } - Text { - width: parent.width - anchors.margins: 4 - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - elide: styleData.elideMode - text: styleData.value !== undefined ? styleData.value : "" - color: styleData.textColor - visible: !styleData.selected - } + Component { + id: editableDelegate + Item { Loader { id: loaderEditor anchors.fill: parent @@ -319,11 +327,73 @@ Window { paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text); } } - sourceComponent: (styleData.selected) ? editor : null + + sourceComponent: + { + if (styleData.role === "value") + { + if (paramsModel.get(styleData.row) === 'undefined') + return null; + if (paramsModel.get(styleData.row).type.indexOf("int") !== -1) + return intViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("bool") !== -1) + return boolViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("string") !== -1) + return stringViewComp; + else if (paramsModel.get(styleData.row).type.indexOf("hash") !== -1) + return hashViewComp; + } + else + return editor; + } + + Component + { + id: intViewComp + QIntTypeView + { + id: intView + text: styleData.value + } + } + + + Component + { + id: boolViewComp + QBoolTypeView + { + id: boolView + text: styleData.value + } + } + + Component + { + id: stringViewComp + QStringTypeView + { + id: stringView + text: styleData.value + } + } + + + Component + { + id: hashViewComp + QHashTypeView + { + id: hashView + text: styleData.value + } + } + Component { id: editor TextInput { id: textinput + readOnly: true color: styleData.textColor text: styleData.value MouseArea { From a78c3668b5616d8eb65fa36b5902534b5ac73cbb Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 30 Jan 2015 00:12:29 +0100 Subject: [PATCH 03/17] - Cleaning. - Bug fix in hash decoding. --- libdevcore/CommonJS.cpp | 2 +- mix/AppContext.cpp | 1 - mix/ClientModel.cpp | 7 +---- mix/ContractCallDataEncoder.cpp | 1 - mix/QVariableDefinition.cpp | 5 +--- mix/QVariableDefinition.h | 8 +++++- mix/qml/QBoolType.qml | 1 - mix/qml/QBoolTypeView.qml | 18 ++++++++----- mix/qml/QHashType.qml | 1 - mix/qml/QHashTypeView.qml | 1 - mix/qml/QIntType.qml | 1 - mix/qml/QIntTypeView.qml | 1 - mix/qml/QRealType.qml | 1 - mix/qml/QStringType.qml | 1 - mix/qml/QStringTypeView.qml | 1 - mix/qml/TransactionDialog.qml | 47 ++++++++++++++++++--------------- 16 files changed, 48 insertions(+), 49 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 1a49d71ec..aa5ce2802 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -64,7 +64,7 @@ std::string unpadRight(std::string _b) while (true) { auto p = _b.find_last_of("0"); - if (p == _b.size() - 1) + if (p == _b.size() - 1 && p != std::string::npos) _b = _b.substr(0, _b.size() - 1); else return _b; diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 49cf64c56..d280d421a 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -61,7 +61,6 @@ void AppContext::load() m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); qmlRegisterType("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); - //qmlRegisterType("org.ethereum.qml.QVariableDefinition", 1, 0, "QVariableDefinition"); qmlRegisterType("org.ethereum.qml.QIntType", 1, 0, "QIntType"); qmlRegisterType("org.ethereum.qml.QRealType", 1, 0, "QRealType"); qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index df489403b..6775817de 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -171,13 +171,8 @@ void ClientModel::executeSequence(std::vector const& _seque throw std::runtime_error("function " + t.functionId.toStdString() + " not found"); c.encode(f); - for (int p = 0; p < t.parameterValues.size(); p++) - { - qDebug() << " encode input parameters : " + t.parameterValues.at(p)->declaration()->type(); - qDebug() << t.parameterValues.at(p)->declaration()->type(); - qDebug() << t.parameterValues.at(p)->value(); + for (unsigned int p = 0; p < t.parameterValues.size(); p++) c.push(t.parameterValues.at(p)->encodeValue()); - } transactonData.emplace_back(c.encodedData()); } diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 4438c9387..7358a91b3 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -35,7 +35,6 @@ using namespace dev::mix; bytes ContractCallDataEncoder::encodedData() { - qDebug() << " encoded data " << QString::fromStdString(toJS(m_encodedData)); return m_encodedData; } diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index 4e29a3a2e..ffa2c04aa 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -66,7 +66,6 @@ dev::bytes QIntType::encodeValue() i = i + dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + 1; std::ostringstream s; s << std::hex << "0x" << i; - qDebug() << " int input " << QString::fromStdString(toJS(padded(jsToBytes(s.str()), 32))); return padded(jsToBytes(s.str()), 32); } @@ -78,7 +77,6 @@ void QIntType::decodeValue(std::string const& _rawValue) bigint = bigint - dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - 1; std::ostringstream s; s << std::dec << bigint; - qDebug() << " int output " << QString::fromStdString(s.str()); setValue(QString::fromStdString(s.str())); } @@ -87,7 +85,7 @@ void QIntType::decodeValue(std::string const& _rawValue) */ dev::bytes QHashType::encodeValue() { - return padded(asBytes(value().toStdString()), 32); + return padded(jsToBytes("0x" + value().toStdString()), 32); } void QHashType::decodeValue(std::string const& _rawValue) @@ -140,7 +138,6 @@ void QStringType::decodeValue(std::string const& _rawValue) */ dev::bytes QBoolType::encodeValue() { - qDebug() << QString::fromStdString(toJS(padded(jsToBytes(value().toStdString()), 32))); return padded(jsToBytes(value().toStdString()), 32); } diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index e58cc81f5..a41a4a7ad 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -41,13 +41,17 @@ public: QVariableDefinition() {} QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {} - /// Return the associated declaration of this variable definition. + /// Return the associated declaration of this variable definition. Invokable from QML. Q_INVOKABLE QVariableDeclaration* declaration() const { return m_dec; } /// Return the variable value. QString value() const { return m_value; } + /// Set a new value for this instance. Invokable from QML. Q_INVOKABLE void setValue(QString _value) { m_value = _value; } + /// Set a new Declaration for this instance. Invokable from QML. Q_INVOKABLE void setDeclaration(QVariableDeclaration* _dec) { m_dec = _dec; } + /// Encode the current value in order to be used as function parameter. virtual bytes encodeValue() = 0; + /// Decode the return value @a _rawValue. virtual void decodeValue(std::string const& _rawValue) = 0; private: @@ -82,6 +86,7 @@ public: QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; + /// @returns an instance of QBigInt for the current value. QBigInt* toBigInt() { return new QBigInt(value()); } }; @@ -127,6 +132,7 @@ public: QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; void decodeValue(std::string const& _rawValue) override; + /// @returns the boolean value for the current definition. bool toBool() { return value() != "0"; } }; diff --git a/mix/qml/QBoolType.qml b/mix/qml/QBoolType.qml index a6dc54035..9f5fe6fd7 100644 --- a/mix/qml/QBoolType.qml +++ b/mix/qml/QBoolType.qml @@ -3,6 +3,5 @@ import org.ethereum.qml.QBoolType 1.0 QBoolType { - property string view: "qrc:/qml/QBoolTypeView.qml" } diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml index b71ec9cf4..4b17f5cc2 100644 --- a/mix/qml/QBoolTypeView.qml +++ b/mix/qml/QBoolTypeView.qml @@ -5,23 +5,29 @@ Item { id: editRoot property string text + property bool defaultValue Rectangle { anchors.fill: parent ComboBox { + Component.onCompleted: + { + text = (defaultValue ? "1" : "0"); + currentIndex = parseInt(text); + } + id: boolCombo anchors.fill: parent onCurrentIndexChanged: { - text = coolComboModel.get(currentIndex).value; - editRoot.textChanged(); + text = comboModel.get(currentIndex).value; } model: ListModel { - id: coolComboModel - ListElement { text: qsTr("True"); value: "1" } - ListElement { text: qsTr("False"); value: "0" } - } + id: comboModel + ListElement { text: qsTr("False"); value: "0" } + ListElement { text: qsTr("True"); value: "1" } + } } } } diff --git a/mix/qml/QHashType.qml b/mix/qml/QHashType.qml index a7913d414..cbd2618cf 100644 --- a/mix/qml/QHashType.qml +++ b/mix/qml/QHashType.qml @@ -3,6 +3,5 @@ import org.ethereum.qml.QHashType 1.0 QHashType { - property string view: "qrc:/qml/QHashTypeView.qml" } diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml index 3e09ca112..7c77ae1c2 100644 --- a/mix/qml/QHashTypeView.qml +++ b/mix/qml/QHashTypeView.qml @@ -10,7 +10,6 @@ Item id: textinput text: text anchors.fill: parent - onTextChanged: editRoot.textChanged() MouseArea { id: mouseArea anchors.fill: parent diff --git a/mix/qml/QIntType.qml b/mix/qml/QIntType.qml index 7533d367f..241bd4a12 100644 --- a/mix/qml/QIntType.qml +++ b/mix/qml/QIntType.qml @@ -3,6 +3,5 @@ import org.ethereum.qml.QIntType 1.0 QIntType { - property string view: "qrc:/qml/QIntTypeView.qml" } diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml index d9156bf19..f794a3b2d 100644 --- a/mix/qml/QIntTypeView.qml +++ b/mix/qml/QIntTypeView.qml @@ -10,7 +10,6 @@ Item id: textinput text: text anchors.fill: parent - onTextChanged: editRoot.textChanged() MouseArea { id: mouseArea anchors.fill: parent diff --git a/mix/qml/QRealType.qml b/mix/qml/QRealType.qml index ba3cf82bf..9a015b1c7 100644 --- a/mix/qml/QRealType.qml +++ b/mix/qml/QRealType.qml @@ -3,6 +3,5 @@ import org.ethereum.qml.QRealType 1.0 QRealType { - property string view: "qrc:/qml/QRealTypeView.qml" } diff --git a/mix/qml/QStringType.qml b/mix/qml/QStringType.qml index ab8db4a42..4113fec20 100644 --- a/mix/qml/QStringType.qml +++ b/mix/qml/QStringType.qml @@ -3,6 +3,5 @@ import org.ethereum.qml.QStringType 1.0 QStringType { - property string view: "qrc:/qml/QStringTypeView.qml" } diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml index d9156bf19..f794a3b2d 100644 --- a/mix/qml/QStringTypeView.qml +++ b/mix/qml/QStringTypeView.qml @@ -10,7 +10,6 @@ Item id: textinput text: text anchors.fill: parent - onTextChanged: editRoot.textChanged() MouseArea { id: mouseArea anchors.fill: parent diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index a98444b85..96b2e0e6b 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -9,7 +9,7 @@ Window { id: modalTransactionDialog modality: Qt.WindowModal width:640 - height:480 + height:640 visible: false property int transactionIndex @@ -41,8 +41,6 @@ Window { rowFunction.visible = !item.executeConstructor; itemParams = item.parameters !== undefined ? item.parameters : {}; - console.log("save parameters : "); - console.log(JSON.stringify(item.qType)); functionsModel.clear(); var functionIndex = -1; var functions = codeModel.code.contract.functions; @@ -72,6 +70,7 @@ Window { } function loadParameters() { + paramsModel.clear(); if (!paramsModel) return; if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { @@ -109,7 +108,7 @@ Window { visible = false; } - function getqTypeParam(name) + function qTypeParam(name) { for (var k in qType) { @@ -145,11 +144,11 @@ Window { var orderedQType = []; for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); - getqTypeParam(parameter.name).setValue(parameter.value); - orderedQType.push(getqTypeParam(parameter.name)); + var qtypeParam = qTypeParam(parameter.name); + qtypeParam.setValue(parameter.value); + orderedQType.push(qtypeParam); item.parameters[parameter.name] = parameter.value; } - console.log(JSON.stringify(qType)); item.qType = orderedQType; return item; } @@ -253,7 +252,10 @@ Window { } TableView { model: paramsModel - Layout.fillWidth: true + Layout.preferredWidth: 120 * 2 + 240 + Layout.minimumHeight: 150 + Layout.preferredHeight: 400 + Layout.maximumHeight: 600 TableViewColumn { role: "name" title: "Name" @@ -267,18 +269,10 @@ Window { TableViewColumn { role: "value" title: "Value" - width: 120 - } - - rowDelegate: - { - return rowDelegate - } - - itemDelegate: - { - return editableDelegate; + width: 240 } + rowDelegate: rowDelegate + itemDelegate: editableDelegate } } } @@ -324,15 +318,20 @@ Window { target: loaderEditor.item onTextChanged: { if (styleData.role === "value" && styleData.row < paramsModel.count) - paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text); + loaderEditor.updateValue(styleData.row, styleData.role, loaderEditor.item.text); } } + function updateValue(row, role, value) + { + paramsModel.setProperty(styleData.row, styleData.role, value); + } + sourceComponent: { if (styleData.role === "value") { - if (paramsModel.get(styleData.row) === 'undefined') + if (paramsModel.get(styleData.row) === undefined) return null; if (paramsModel.get(styleData.row).type.indexOf("int") !== -1) return intViewComp; @@ -365,6 +364,12 @@ Window { { id: boolView text: styleData.value + defaultValue: true + Component.onCompleted: + { + //default value + loaderEditor.updateValue(styleData.row, styleData.role, "1"); + } } } From eab72b22b35c015fa6c1013db44be98de6437745 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 30 Jan 2015 00:28:14 +0100 Subject: [PATCH 04/17] Cleaning --- libdevcore/CommonJS.h | 6 +++--- mix/ClientModel.cpp | 2 +- mix/ContractCallDataEncoder.cpp | 4 ++-- mix/ContractCallDataEncoder.h | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 4f7ef8495..6b75d70dc 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -48,15 +48,15 @@ inline std::string toJS(dev::bytes const& _n) /// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex. bytes jsToBytes(std::string const& _s); -/// Add '0' on the head of _b until _l. +/// Add '0' on the head of @a _b until @a _l. bytes padded(bytes _b, unsigned _l); -/// Add '0' on the queue of _b until _l. +/// Add '0' on the queue of @a _b until @a _l. bytes paddedRight(bytes _b, unsigned _l); /// Remove all trailing '0' std::string unpadRight(std::string _b); /// Removing all trailing '0'. Returns empty array if input contains only '0' char. bytes unpadded(bytes _s); -/// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'. +/// Remove all '0' on the head of @a _s. Returns 0 if @a _s contains only '0'. std::string unpadLeft(std::string _s); /// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256. std::string prettyU256(u256 _n); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 6775817de..393d08657 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -171,7 +171,7 @@ void ClientModel::executeSequence(std::vector const& _seque throw std::runtime_error("function " + t.functionId.toStdString() + " not found"); c.encode(f); - for (unsigned int p = 0; p < t.parameterValues.size(); p++) + for (int p = 0; p < t.parameterValues.size(); p++) c.push(t.parameterValues.at(p)->encodeValue()); transactonData.emplace_back(c.encodedData()); } diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 7358a91b3..19e40936d 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -44,12 +44,12 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function) m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end()); } -void ContractCallDataEncoder::push(bytes _b) +void ContractCallDataEncoder::push(bytes const& _b) { m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end()); } -QList ContractCallDataEncoder::decode(QList _returnParameters, bytes _value) +QList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes const& _value) { QList r; std::string returnValue = toJS(_value); diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index 27baef8ee..d64745052 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -44,11 +44,11 @@ public: /// Encode hash of the function to call. void encode(QFunctionDefinition const* _function); /// Decode variable in order to be sent to QML view. - QList decode(QList _dec, bytes _value); + QList decode(QList const& _dec, bytes const& _value); /// Get all encoded data encoded by encode function. bytes encodedData(); - /// Push the given @ _b to the current param context. - void push(bytes _b); + /// Push the given @a _b to the current param context. + void push(bytes const& _b); private: bytes m_encodedData; From a93319623a1df9ab64ed831356b9a8b6cdd93d6c Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 1 Feb 2015 17:23:13 +0100 Subject: [PATCH 05/17] misc changes --- libdevcore/CommonJS.cpp | 28 ++++++-------- libdevcore/CommonJS.h | 6 +-- mix/ClientModel.cpp | 6 +++ mix/ContractCallDataEncoder.cpp | 13 ++++--- mix/ContractCallDataEncoder.h | 2 +- mix/QBigInt.h | 4 +- mix/QVariableDeclaration.h | 2 +- mix/QVariableDefinition.cpp | 65 ++++++++++++++++----------------- mix/QVariableDefinition.h | 28 +++++++++----- mix/qml/QBoolTypeView.qml | 14 +++++-- mix/qml/QHashTypeView.qml | 1 + mix/qml/QStringTypeView.qml | 1 + mix/qml/TransactionDialog.qml | 10 ++--- 13 files changed, 99 insertions(+), 81 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index aa5ce2802..8cdb27954 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -47,9 +47,8 @@ bytes padded(bytes _b, unsigned _l) bytes paddedRight(bytes _b, unsigned _l) { - while (_b.size() < _l) - _b.insert(_b.end(), 0); - return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); + _b.resize(_l); + return _b; } bytes unpadded(bytes _b) @@ -59,24 +58,21 @@ bytes unpadded(bytes _b) return _b; } -std::string unpadRight(std::string _b) +bytes unpadLeft(bytes _b) { + int i = 0; + if (_b.size() == 0) + return _b; while (true) { - auto p = _b.find_last_of("0"); - if (p == _b.size() - 1 && p != std::string::npos) - _b = _b.substr(0, _b.size() - 1); + if (_b.at(i) == byte(0)) + i++; else - return _b; + break; } -} - -std::string unpadLeft(std::string _b) -{ - auto p = _b.find_first_not_of('0'); - if (p == std::string::npos) - return "0"; - return _b.substr(p, _b.length() - 1); + if (i != 0) + _b.erase(_b.begin(), _b.begin() + i); + return _b; } std::string prettyU256(u256 _n) diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index 6b75d70dc..59e6c1d34 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -52,12 +52,10 @@ bytes jsToBytes(std::string const& _s); bytes padded(bytes _b, unsigned _l); /// Add '0' on the queue of @a _b until @a _l. bytes paddedRight(bytes _b, unsigned _l); -/// Remove all trailing '0' -std::string unpadRight(std::string _b); /// Removing all trailing '0'. Returns empty array if input contains only '0' char. bytes unpadded(bytes _s); -/// Remove all '0' on the head of @a _s. Returns 0 if @a _s contains only '0'. -std::string unpadLeft(std::string _s); +/// Remove all 0 byte on the head of @a _s. +bytes unpadLeft(bytes _s); /// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256. std::string prettyU256(u256 _n); /// Convert h256 into user-readable string (by directly using std::string constructor). diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 393d08657..e71280821 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -170,6 +170,12 @@ void ClientModel::executeSequence(std::vector const& _seque if (!f) throw std::runtime_error("function " + t.functionId.toStdString() + " not found"); + for (int k = 0; k < f->parametersList() .size(); k++) + { + if (f->parametersList().at(k)->type() != t.parameterValues.at(k)->declaration()->type()) + throw std::runtime_error("list of parameters has been changed. Need to update this transaction"); + } + c.encode(f); for (int p = 0; p < t.parameterValues.size(); p++) c.push(t.parameterValues.at(p)->encodeValue()); diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 19e40936d..bdec95ca4 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -49,11 +49,9 @@ void ContractCallDataEncoder::push(bytes const& _b) m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end()); } -QList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes const& _value) +QList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes _value) { QList r; - std::string returnValue = toJS(_value); - returnValue = returnValue.substr(2, returnValue.length() - 1); for (int k = 0; k <_returnParameters.length(); k++) { QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k); @@ -68,9 +66,14 @@ QList ContractCallDataEncoder::decode(QListtype().contains("hash") || dec->type().contains("address")) def = new QHashType(dec, QString()); - def->decodeValue(returnValue); + else + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found")); + + bytes rawParam(_value.begin(), _value.begin() + 32); + def->decodeValue(rawParam); r.push_back(def); - returnValue = returnValue.substr(32 * 2, returnValue.length() - 1); + if (_value.size() > 32) + _value = bytes(_value.begin() + 32, _value.end()); qDebug() << "decoded return value : " << dec->type() << " " << def->value(); } return r; diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index d64745052..718beb8e0 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -44,7 +44,7 @@ public: /// Encode hash of the function to call. void encode(QFunctionDefinition const* _function); /// Decode variable in order to be sent to QML view. - QList decode(QList const& _dec, bytes const& _value); + QList decode(QList const& _dec, bytes _value); /// Get all encoded data encoded by encode function. bytes encodedData(); /// Push the given @a _b to the current param context. diff --git a/mix/QBigInt.h b/mix/QBigInt.h index 0f5c88c43..c6ec72305 100644 --- a/mix/QBigInt.h +++ b/mix/QBigInt.h @@ -36,7 +36,7 @@ namespace dev namespace mix { -using BigIntVariant = boost::variant; +using BigIntVariant = boost::variant; struct add: public boost::static_visitor { @@ -75,7 +75,7 @@ public: QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){ QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } - QBigInt(QString const& _value, QObject* _parent = 0): QObject(_parent) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); setValue(_value); } + QBigInt(dev::s256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } ~QBigInt() {} /// @returns the current used big integer. diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index 0d091b035..2670a4dc3 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -40,7 +40,7 @@ public: QVariableDeclaration() {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} QVariableDeclaration(solidity::ParamDescription const& _v): QBasicNodeDefinition(_v.getName()), m_type(QString::fromStdString(_v.getType())) {} - Q_INVOKABLE QString type() const { return m_type; } + QString type() const { return m_type; } private: QString m_type; diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index ffa2c04aa..5049283da 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -59,25 +59,30 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx) /* * QIntType */ +void QIntType::setValue(dev::bigint _value) +{ + m_bigIntvalue = _value; + std::stringstream str; + str << std::dec << m_bigIntvalue; + m_value = QString::fromStdString(str.str()); +} + dev::bytes QIntType::encodeValue() { dev::bigint i(value().toStdString()); if (i < 0) i = i + dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + 1; - std::ostringstream s; - s << std::hex << "0x" << i; - return padded(jsToBytes(s.str()), 32); + bytes ret(32); + toBigEndian(i, ret); + return ret; } -void QIntType::decodeValue(std::string const& _rawValue) +void QIntType::decodeValue(dev::bytes const& _rawValue) { - std::string rawParam = _rawValue.substr(0, 32 * 2); - dev::bigint bigint = dev::bigint("0x" + rawParam); + dev::bigint bigint = dev::fromBigEndian(_rawValue); if (((bigint >> 32) & 1) == 1) bigint = bigint - dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - 1; - std::ostringstream s; - s << std::dec << bigint; - setValue(QString::fromStdString(s.str())); + setValue(bigint); } /* @@ -85,14 +90,15 @@ void QIntType::decodeValue(std::string const& _rawValue) */ dev::bytes QHashType::encodeValue() { - return padded(jsToBytes("0x" + value().toStdString()), 32); + QByteArray b = value().toUtf8(); + bytes r = bytes(b.begin(), b.end()); + return padded(r, 32); } -void QHashType::decodeValue(std::string const& _rawValue) +void QHashType::decodeValue(dev::bytes const& _rawValue) { - std::string rawParam = _rawValue.substr(0, 32 * 2); - std::string unPadded = unpadLeft(rawParam); - setValue(QString::fromStdString(unPadded)); + std::string _ret = asString(unpadLeft(_rawValue)); + setValue(QString::fromStdString(_ret)); } /* @@ -103,7 +109,7 @@ dev::bytes QRealType::encodeValue() return bytes(); } -void QRealType::decodeValue(std::string const& _rawValue) +void QRealType::decodeValue(dev::bytes const& _rawValue) { Q_UNUSED(_rawValue); } @@ -113,24 +119,14 @@ void QRealType::decodeValue(std::string const& _rawValue) */ dev::bytes QStringType::encodeValue() { - qDebug() << QString::fromStdString(toJS(paddedRight(asBytes(value().toStdString()), 32))); - return paddedRight(asBytes(value().toStdString()), 32); + QByteArray b = value().toUtf8(); + bytes r = bytes(b.begin(), b.end()); + return paddedRight(r, 32); } -void QStringType::decodeValue(std::string const& _rawValue) +void QStringType::decodeValue(dev::bytes const& _rawValue) { - std::string rawParam = _rawValue.substr(0, 32 * 2); - rawParam = unpadRight(rawParam); - std::string res; - res.reserve(rawParam.size() / 2); - for (unsigned int i = 0; i < rawParam.size(); i += 2) - { - std::istringstream iss(rawParam.substr(i, 2)); - int temp; - iss >> std::hex >> temp; - res += static_cast(temp); - } - setValue(QString::fromStdString(res)); + setValue(QString::fromUtf8((char*)_rawValue.data())); } /* @@ -141,9 +137,10 @@ dev::bytes QBoolType::encodeValue() return padded(jsToBytes(value().toStdString()), 32); } -void QBoolType::decodeValue(std::string const& _rawValue) +void QBoolType::decodeValue(dev::bytes const& _rawValue) { - std::string rawParam = _rawValue.substr(0, 32 * 2); - std::string unpadded = unpadLeft(rawParam); - setValue(QString::fromStdString(unpadded)); + byte ret = _rawValue.at(_rawValue.size() - 1); + bool boolRet = (ret == byte(1)); + m_boolValue = boolRet; + m_value = m_boolValue ? "1" : "0"; } diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index a41a4a7ad..ae9bf9459 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -52,10 +52,12 @@ public: /// Encode the current value in order to be used as function parameter. virtual bytes encodeValue() = 0; /// Decode the return value @a _rawValue. - virtual void decodeValue(std::string const& _rawValue) = 0; + virtual void decodeValue(dev::bytes const& _rawValue) = 0; -private: +protected: QString m_value; + +private: QVariableDeclaration* m_dec; }; @@ -85,9 +87,14 @@ public: QIntType() {} QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; - void decodeValue(std::string const& _rawValue) override; + void decodeValue(dev::bytes const& _rawValue) override; /// @returns an instance of QBigInt for the current value. - QBigInt* toBigInt() { return new QBigInt(value()); } + QBigInt* toBigInt() { return new QBigInt(m_bigIntvalue); } + dev::bigint bigInt() { return m_bigIntvalue; } + void setValue(dev::bigint _value); + +private: + dev::bigint m_bigIntvalue; }; class QRealType: public QVariableDefinition @@ -98,7 +105,7 @@ public: QRealType() {} QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; - void decodeValue(std::string const& _rawValue) override; + void decodeValue(dev::bytes const& _rawValue) override; }; class QStringType: public QVariableDefinition @@ -109,7 +116,7 @@ public: QStringType() {} QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; - void decodeValue(std::string const& _rawValue) override; + void decodeValue(dev::bytes const& _rawValue) override; }; class QHashType: public QVariableDefinition @@ -120,7 +127,7 @@ public: QHashType() {} QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; - void decodeValue(std::string const& _rawValue) override; + void decodeValue(dev::bytes const& _rawValue) override; }; class QBoolType: public QVariableDefinition @@ -131,9 +138,12 @@ public: QBoolType() {} QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} dev::bytes encodeValue() override; - void decodeValue(std::string const& _rawValue) override; + void decodeValue(dev::bytes const& _rawValue) override; /// @returns the boolean value for the current definition. - bool toBool() { return value() != "0"; } + bool toBool() { return m_boolValue; } + +private: + bool m_boolValue; }; } diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml index 4b17f5cc2..a52601bdb 100644 --- a/mix/qml/QBoolTypeView.qml +++ b/mix/qml/QBoolTypeView.qml @@ -5,22 +5,28 @@ Item { id: editRoot property string text - property bool defaultValue + property string defaultValue + Rectangle { anchors.fill: parent ComboBox { + property bool inited: false Component.onCompleted: { - text = (defaultValue ? "1" : "0"); - currentIndex = parseInt(text); + if (text === "") + currentIndex = parseInt(defaultValue); + else + currentIndex = parseInt(text); + inited = true } id: boolCombo anchors.fill: parent onCurrentIndexChanged: { - text = comboModel.get(currentIndex).value; + if (inited) + text = comboModel.get(currentIndex).value; } model: ListModel { diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml index 7c77ae1c2..e36514fab 100644 --- a/mix/qml/QHashTypeView.qml +++ b/mix/qml/QHashTypeView.qml @@ -10,6 +10,7 @@ Item id: textinput text: text anchors.fill: parent + wrapMode: Text.WrapAnywhere MouseArea { id: mouseArea anchors.fill: parent diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml index f794a3b2d..a78fc1d26 100644 --- a/mix/qml/QStringTypeView.qml +++ b/mix/qml/QStringTypeView.qml @@ -10,6 +10,7 @@ Item id: textinput text: text anchors.fill: parent + wrapMode: Text.WrapAnywhere MouseArea { id: mouseArea anchors.fill: parent diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 96b2e0e6b..f81de10a5 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -356,19 +356,19 @@ Window { } } - Component { id: boolViewComp QBoolTypeView { id: boolView - text: styleData.value - defaultValue: true + defaultValue: "1" Component.onCompleted: { - //default value - loaderEditor.updateValue(styleData.row, styleData.role, "1"); + loaderEditor.updateValue(styleData.row, styleData.role, + (paramsModel.get(styleData.row).value === "" ? defaultValue : + paramsModel.get(styleData.row).value)); + text = (paramsModel.get(styleData.row).value === "" ? defaultValue : paramsModel.get(styleData.row).value); } } } From a3a9762c96ad758cfea67857f384fa56fe136d96 Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 1 Feb 2015 20:03:27 +0100 Subject: [PATCH 06/17] display return parameters in transaction list --- mix/ClientModel.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index b8f7c9a2b..ca7849412 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -207,15 +207,14 @@ void ClientModel::executeSequence(std::vector const& _seque if (!f) BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); - for (int k = 0; k < f->parametersList() .size(); k++) - { - if (f->parametersList().at(k)->type() != transaction.parameterValues.at(k)->declaration()->type()) - BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(f->parametersList().at(k)->type().toStdString())); - } - encoder.encode(f); for (int p = 0; p < transaction.parameterValues.size(); p++) + { + if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) + BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(f->parametersList().at(p)->type().toStdString())); encoder.push(transaction.parameterValues.at(p)->encodeValue()); + } + if (transaction.functionId.isEmpty()) { @@ -229,10 +228,6 @@ void ClientModel::executeSequence(std::vector const& _seque else { callContract(m_contractAddress, encoder.encodedData(), transaction); - - // Used to log return values. TODO move this to QML. - ExecutionResult const& last = m_client->record().back().transactions.back(); - encoder.decode(f->returnParameters(), last.returnValue); } } onNewTransaction(); @@ -331,11 +326,6 @@ void ClientModel::onNewTransaction() bool creation = tr.contractAddress != 0; - if (creation) - returned = QString::fromStdString(toJS(tr.contractAddress)); - else - returned = QString::fromStdString(toJS(tr.returnValue)); - //TODO: handle value transfer FixedHash<4> functionHash; bool call = false; @@ -364,6 +354,10 @@ void ClientModel::onNewTransaction() function = QObject::tr(""); } + if (creation) + returned = QString::fromStdString(toJS(tr.contractAddress)); + + QList returnValues; if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress)) { auto compilerRes = m_context->codeModel()->code(); @@ -373,7 +367,13 @@ void ClientModel::onNewTransaction() { QFunctionDefinition* funcDef = def->getFunction(functionHash); if (funcDef) + { function = funcDef->name(); + ContractCallDataEncoder encoder; + returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); + for (auto const& var: returnValues) + returned += var->value() + " | "; + } } } From afa9b4337fa9ee35640e7ba2d6663bcbc98b3e43 Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 1 Feb 2015 23:11:14 +0100 Subject: [PATCH 07/17] Integrate solidity type with project files. --- mix/AppContext.cpp | 1 + mix/ClientModel.cpp | 3 +- mix/QVariableDeclaration.h | 5 +++- mix/qml/QVariableDeclaration.qml | 7 +++++ mix/qml/StateListModel.qml | 47 ++++++++++++++++++++++++++++---- mix/res.qrc | 1 + 6 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 mix/qml/QVariableDeclaration.qml diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 572ad7bbd..e27eac9fd 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -68,6 +68,7 @@ void AppContext::load() qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); qmlRegisterType("org.ethereum.qml.QHashType", 1, 0, "QHashType"); qmlRegisterType("org.ethereum.qml.QBoolType", 1, 0, "QBoolType"); + qmlRegisterType("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index ca7849412..93bcc7c92 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -357,7 +357,6 @@ void ClientModel::onNewTransaction() if (creation) returned = QString::fromStdString(toJS(tr.contractAddress)); - QList returnValues; if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress)) { auto compilerRes = m_context->codeModel()->code(); @@ -370,7 +369,7 @@ void ClientModel::onNewTransaction() { function = funcDef->name(); ContractCallDataEncoder encoder; - returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); + QList returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); for (auto const& var: returnValues) returned += var->value() + " | "; } diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index 771f334e8..fcd83cb30 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -34,13 +34,14 @@ namespace mix class QVariableDeclaration: public QBasicNodeDefinition { Q_OBJECT - Q_PROPERTY(QString type READ type CONSTANT) + Q_PROPERTY(QString type READ type WRITE setType) public: QVariableDeclaration() {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} QVariableDeclaration(std::string const& _name, std::string const& _type): QBasicNodeDefinition(_name), m_type(QString::fromStdString(_type)) {} QString type() const { return m_type; } + void setType(QString _type) { m_type = _type; } private: QString m_type; @@ -48,3 +49,5 @@ private: } } + +Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*) diff --git a/mix/qml/QVariableDeclaration.qml b/mix/qml/QVariableDeclaration.qml new file mode 100644 index 000000000..dc21d40a7 --- /dev/null +++ b/mix/qml/QVariableDeclaration.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import org.ethereum.qml.QVariableDeclaration 1.0 + +QVariableDeclaration +{ +} + diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 5f4b7e20e..3d60414cc 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -31,12 +31,30 @@ Item { stdContract: t.stdContract, parameters: {} }; - for (var key in t.parameters) { - var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); - var param = intComponent.createObject(); - param.setValue(t.parameters[key]); - r.parameters[key] = param; + var qType = []; + for (var key in t.parameters) + { + r.parameters[key] = t.parameters[key].value; + var type = t.parameters[key].type; + var varComponent; + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + + var param = varComponent.createObject(stateListModel); + var dec = Qt.createComponent("qrc:/qml/QVariableDeclaration.qml"); + param.setDeclaration(dec.createObject(stateListModel, { "type": type })); + param.setValue(r.parameters[key]); + qType.push(param); } + r.qType = qType; return r; } @@ -48,6 +66,16 @@ Item { }; } + function getParamType(param, params) + { + for (var k in params) + { + if (params[k].declaration.name === param) + return params[k].declaration.type; + } + return ''; + } + function toPlainTransactionItem(t) { var r = { functionId: t.functionId, @@ -60,7 +88,14 @@ Item { parameters: {} }; for (var key in t.parameters) - r.parameters[key] = t.parameters[key]; + { + var param = { + name: key, + value: t.parameters[key], + type: getParamType(key, t.qType) + } + r.parameters[key] = param; + } return r; } diff --git a/mix/res.qrc b/mix/res.qrc index 02b58bb8e..82f9456be 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -63,5 +63,6 @@ qml/TransactionLog.qml res/mix_256x256x32.png qml/CallStack.qml + qml/QVariableDeclaration.qml From a2f495c4bb12fc155b4016ed9011a4bd8b4c901b Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 1 Feb 2015 23:24:03 +0100 Subject: [PATCH 08/17] fixed collision while merging --- mix/qml/StateList.qml | 58 ------------------------------------------- 1 file changed, 58 deletions(-) diff --git a/mix/qml/StateList.qml b/mix/qml/StateList.qml index ee5048e14..ad14cf30e 100644 --- a/mix/qml/StateList.qml +++ b/mix/qml/StateList.qml @@ -27,64 +27,6 @@ Rectangle { action: addStateAction } - StateDialog { - id: stateDialog - onAccepted: { - var item = stateDialog.getItem(); - if (stateDialog.stateIndex < stateListModel.count) { - stateList[stateDialog.stateIndex] = item; - stateListModel.set(stateDialog.stateIndex, item); - } else { - stateList.push(item); - stateListModel.append(item); - } - stateListModel.save(); - } - } - - ListModel { - id: stateListModel - - function addState() { - var ether = QEtherHelper.createEther("100000000000000000000000000", QEther.Wei); - var item = { - title: "", - balance: ether, - transactions: [] - }; - - var ctorTr = { - value: QEtherHelper.createEther("100", QEther.Wei), - functionId: qsTr("Constructor"), - gas: QEtherHelper.createEther("125000", QEther.Wei), - gasPrice: QEtherHelper.createEther("10000000000000", QEther.Wei), - executeConstructor: true - }; - - item.transactions.push(ctorTr); - stateDialog.open(stateListModel.count, item); - } - - function editState(index) { - stateDialog.open(index, stateList[index]); - } - - function runState(index) { - var item = stateList[index]; - clientModel.debugState(item); - } - - function deleteState(index) { - stateListModel.remove(index); - stateList.splice(index, 1); - save(); - } - - function save() { - projectModel.saveProject(); - } - } - Component { id: renderDelegate Item { From 1592bb2651d3eb43e656177cc895720f3c69b294 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Feb 2015 10:06:34 +0100 Subject: [PATCH 09/17] Coding standards. --- libdevcore/CommonJS.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 8cdb27954..9c20bdd53 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -63,13 +63,13 @@ bytes unpadLeft(bytes _b) int i = 0; if (_b.size() == 0) return _b; + while (true) - { if (_b.at(i) == byte(0)) i++; else break; - } + if (i != 0) _b.erase(_b.begin(), _b.begin() + i); return _b; From 1cd85e9cc9a7fb004e3caab14e59a51425a8278e Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Feb 2015 12:15:42 +0100 Subject: [PATCH 10/17] ux improvements --- mix/main.cpp | 2 + mix/qml/MainContent.qml | 215 +++++++++++++++++-------------------- mix/qml/ProjectList.qml | 2 +- mix/qml/ProjectModel.qml | 3 +- mix/qml/StateListModel.qml | 2 +- mix/qml/WebPreview.qml | 2 +- mix/qml/html/codeeditor.js | 1 + mix/qml/js/ProjectModel.js | 3 +- mix/qml/main.qml | 39 ++++--- 9 files changed, 133 insertions(+), 136 deletions(-) diff --git a/mix/main.cpp b/mix/main.cpp index f7213f0fc..b24b8a549 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -35,6 +35,8 @@ int main(int _argc, char* _argv[]) //work around ubuntu appmenu-qt5 bug //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 putenv((char*)"QT_QPA_PLATFORMTHEME="); + putenv((char*)"QSG_RENDER_LOOP=threaded"); + putenv((char*)"QT_IM_MODULE="); #endif try { diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 1ed1c11d2..247de143f 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -23,14 +23,20 @@ Rectangle { property alias rightViewVisible : rightView.visible property alias webViewVisible : webPreview.visible + property alias projectViewVisible : projectList.visible + property alias runOnProjectLoad : mainSettings.runOnProjectLoad property bool webViewHorizontal : codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally - - onWidthChanged: - { - if (rightView.visible) - contentView.width = parent.width - projectList.width - rightView.width; - else - contentView.width = parent.width - projectList.width; + property bool firstCompile: true + + Connections { + target: codeModel + onCompilationComplete: { + if (firstCompile) { + firstCompile = false; + if (codeModel.code.successful && runOnProjectLoad) + startQuickDebugging(); + } + } } function startQuickDebugging() @@ -40,15 +46,11 @@ Rectangle { } function toggleRightView() { - if (!rightView.visible) - rightView.show(); - else - rightView.hide(); + rightView.visible = !rightView.visible; } function ensureRightView() { - if (!rightView.visible) - rightView.show(); + rightView.visible = true; } function rightViewIsVisible() @@ -65,6 +67,10 @@ Rectangle { webPreview.visible = !webPreview.visible; } + function toggleProjectView() { + projectList.visible = !projectList.visible; + } + function toggleWebPreviewOrientation() { codeWebSplitter.orientation = (codeWebSplitter.orientation === Qt.Vertical ? Qt.Horizontal : Qt.Vertical); } @@ -75,19 +81,18 @@ Rectangle { } Settings { - id: mainLayoutSettings + id: mainSettings property alias codeWebOrientation: codeWebSplitter.orientation property alias webWidth: webPreview.width property alias webHeight: webPreview.height + property alias showProjectView: projectList.visible + property bool runOnProjectLoad: false } - GridLayout + ColumnLayout { anchors.fill: parent - rows: 2 - flow: GridLayout.TopToBottom - columnSpacing: 0 - rowSpacing: 0 + spacing: 0 Rectangle { width: parent.width height: 50 @@ -128,116 +133,90 @@ Rectangle { property alias rightViewWidth: rightView.width } - ProjectList { - anchors.left: parent.left - id: projectList - width: 200 - height: parent.height - Layout.minimumWidth: 200 - } - - Splitter + SplitView { - id: resizeLeft - itemToStick: projectList - itemMinimumWidth: projectList.Layout.minimumWidth - direction: "right" - brother: contentView - color: "#a2a2a2" - } - - Rectangle { - anchors.left: projectList.right - id: contentView - width: parent.width - projectList.width - height: parent.height - SplitView { - handleDelegate: Rectangle { - width: 4 - height: 4 - color: "#cccccc" - } - id: codeWebSplitter - anchors.fill: parent - orientation: Qt.Vertical - CodeEditorView { - height: parent.height * 0.6 - anchors.top: parent.top - Layout.fillWidth: true - Layout.fillHeight: true - } - WebPreview { - id: webPreview - height: parent.height * 0.4 - Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical - Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal - Layout.minimumHeight: 200 - Layout.minimumWidth: 200 - } + anchors.fill: parent + handleDelegate: Rectangle { + width: 4 + height: 4 + color: "#cccccc" } - } - - Splitter - { - id: resizeRight - visible: false; - itemToStick: rightView - itemMinimumWidth: rightView.Layout.minimumWidth - direction: "left" - brother: contentView - color: "#a2a2a2" - } - - Rectangle { - visible: false; - id: rightView; + orientation: Qt.Horizontal - Keys.onEscapePressed: hide() - - function show() { - visible = true; - resizeRight.visible = true; - contentView.width = parent.width - projectList.width - rightView.width; + ProjectList { + id: projectList + width: 200 + Layout.minimumWidth: 180 + Layout.fillHeight: true } - - function hide() { - resizeRight.visible = false; - visible = false; - contentView.width = parent.width - projectList.width; + Rectangle { + id: contentView + Layout.fillHeight: true + Layout.fillWidth: true + SplitView { + handleDelegate: Rectangle { + width: 4 + height: 4 + color: "#cccccc" + } + id: codeWebSplitter + anchors.fill: parent + orientation: Qt.Vertical + CodeEditorView { + height: parent.height * 0.6 + anchors.top: parent.top + Layout.fillWidth: true + Layout.fillHeight: true + } + WebPreview { + id: webPreview + height: parent.height * 0.4 + Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical + Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal + Layout.minimumHeight: 200 + Layout.minimumWidth: 200 + } + } } - height: parent.height; - width: 515 - Layout.minimumWidth: 515 - anchors.right: parent.right Rectangle { - anchors.fill: parent; - id: rightPaneView - TabView { - id: rightPaneTabs - tabsVisible: true - antialiasing: true - anchors.fill: parent - style: TabViewStyle { - frameOverlap: 1 - tabBar: - Rectangle { + visible: false; + id: rightView; + Layout.fillHeight: true + Keys.onEscapePressed: visible = false + height: parent.height; + width: 515 + Layout.minimumWidth: 515 + anchors.right: parent.right + Rectangle { + anchors.fill: parent; + id: rightPaneView + TabView { + id: rightPaneTabs + tabsVisible: true + antialiasing: true + anchors.fill: parent + style: TabViewStyle { + frameOverlap: 1 + tabBar: + Rectangle { + color: "#ededed" + id: background + } + tab: Rectangle { color: "#ededed" - id: background + implicitWidth: 80 + implicitHeight: 20 + radius: 2 + Text { + anchors.centerIn: parent + text: styleData.title + color: styleData.selected ? "#7da4cd" : "#202020" + } } - tab: Rectangle { - color: "#ededed" - implicitWidth: 80 - implicitHeight: 20 - radius: 2 - Text { - anchors.centerIn: parent - text: styleData.title - color: styleData.selected ? "#7da4cd" : "#202020" + frame: Rectangle { } } - frame: Rectangle { - } } } } diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index 30f945706..e4e57455d 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -3,7 +3,7 @@ import QtQuick.Window 2.0 import QtQuick.Layouts 1.0 import QtQuick.Controls 1.0 -Item { +Rectangle { property bool renameMode: false; ColumnLayout { anchors.fill: parent diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index 14716483c..49e63e184 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -10,7 +10,8 @@ Item { id: projectModel signal projectClosed - signal projectLoaded(var projectData) + signal projectLoading(var projectData) + signal projectLoaded() signal documentOpened(var document) signal documentRemoved(var documentId) signal documentUpdated(var documentId) //renamed diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index c158112e1..6f8fd3a1a 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -70,7 +70,7 @@ Item { stateListModel.clear(); stateList = []; } - onProjectLoaded: { + onProjectLoading: { if (!projectData.states) projectData.states = []; if (projectData.defaultStateIndex !== undefined) diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index bd48210ef..e95a85fde 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -86,7 +86,7 @@ Item { updateDocument(documentId, function(i) { pageListModel.set(i, projectModel.getDocument(documentId)) } ) } - onProjectLoaded: { + onProjectLoading: { for (var i = 0; i < target.listModel.count; i++) { var document = target.listModel.get(i); if (document.isHtml) { diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 2cebc121e..5b3e5450f 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -31,6 +31,7 @@ getText = function() { setTextBase64 = function(text) { editor.setValue(window.atob(text)); + editor.getDoc().clearHistory(); editor.focus(); }; diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index ed7ebd3ce..7e1050385 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -73,7 +73,8 @@ function loadProject(path) { addFile(projectData.files[i]); } projectSettings.lastProjectPath = path; - projectLoaded(projectData); + projectLoading(projectData); + projectLoaded() } function addExistingFile() { diff --git a/mix/qml/main.qml b/mix/qml/main.qml index a0a4ba423..b2fc38b0a 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -36,14 +36,16 @@ ApplicationWindow { Menu { title: qsTr("Debug") MenuItem { action: debugRunAction } - MenuItem { action: debugResetStateAction } MenuItem { action: mineAction } + MenuSeparator {} + MenuItem { action: toggleRunOnLoadAction } } Menu { title: qsTr("Windows") MenuItem { action: openNextDocumentAction } MenuItem { action: openPrevDocumentAction } MenuSeparator {} + MenuItem { action: toggleProjectNavigatorAction } MenuItem { action: showHideRightPanelAction } MenuItem { action: toggleWebPreviewAction } MenuItem { action: toggleWebPreviewOrientationAction } @@ -82,47 +84,58 @@ ApplicationWindow { Action { id: mineAction - text: "Mine" + text: qsTr("Mine") shortcut: "Ctrl+M" onTriggered: clientModel.mine(); enabled: codeModel.hasContract && !clientModel.running } Action { id: debugRunAction - text: "&Run" + text: qsTr("Run") shortcut: "F5" onTriggered: mainContent.startQuickDebugging() enabled: codeModel.hasContract && !clientModel.running } - Action { - id: debugResetStateAction - text: "Reset &State" - shortcut: "F6" - onTriggered: clientModel.resetState(); - } - Action { id: toggleWebPreviewAction - text: "Show Web View" + text: qsTr("Show Web View") shortcut: "F2" checkable: true checked: mainContent.webViewVisible onTriggered: mainContent.toggleWebPreview(); } + Action { + id: toggleProjectNavigatorAction + text: qsTr("Show Project Navigator") + shortcut: "Alt+0" + checkable: true + checked: mainContent.projectViewVisible + onTriggered: mainContent.toggleProjectView(); + } + Action { id: toggleWebPreviewOrientationAction - text: "Horizontal Web View" + text: qsTr("Horizontal Web View") shortcut: "" checkable: true checked: mainContent.webViewHorizontal onTriggered: mainContent.toggleWebPreviewOrientation(); } + Action { + id: toggleRunOnLoadAction + text: qsTr("Load State on Startup") + shortcut: "" + checkable: true + checked: mainContent.runOnProjectLoad + onTriggered: mainContent.runOnProjectLoad = !mainContent.runOnProjectLoad + } + Action { id: showHideRightPanelAction - text: "Show Right View" + text: qsTr("Show Right View") shortcut: "F7" checkable: true checked: mainContent.rightViewVisible From fca289876fce4f3cf4a8d0b27fa0e7148bf9cc9f Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Feb 2015 16:47:18 +0100 Subject: [PATCH 11/17] removed splitter.qml --- libjsqrc/ethereumjs/dist/ethereum.js | 7 ++--- mix/qml/Splitter.qml | 47 ---------------------------- mix/res.qrc | 1 - 3 files changed, 3 insertions(+), 52 deletions(-) delete mode 100644 mix/qml/Splitter.qml diff --git a/libjsqrc/ethereumjs/dist/ethereum.js b/libjsqrc/ethereumjs/dist/ethereum.js index 0f30280f9..5c912dbba 100644 --- a/libjsqrc/ethereumjs/dist/ethereum.js +++ b/libjsqrc/ethereumjs/dist/ethereum.js @@ -903,9 +903,8 @@ var ProviderManager = function() { data.data._id = self.id; self.id++; var result = self.provider.send(data.data); - - result = JSON.parse(result); - + result = JSON.parse(result); + // dont call the callback if result is not an array, or empty one if (result.error || !(result.result instanceof Array) || result.result.length === 0) { return; @@ -1520,4 +1519,4 @@ module.exports = web3; },{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":8,"./lib/qtsync":9,"./lib/web3":12}]},{},["web3"]) -//# sourceMappingURL=ethereum.js.map \ No newline at end of file +//# sourceMappingURL=ethereum.js.map diff --git a/mix/qml/Splitter.qml b/mix/qml/Splitter.qml deleted file mode 100644 index 341dc4450..000000000 --- a/mix/qml/Splitter.qml +++ /dev/null @@ -1,47 +0,0 @@ -import QtQuick 2.2 - -Rectangle { - property variant itemToStick; - property int itemMinimumWidth; - property string direction; - property variant brother; - - Component.onCompleted: - { - if (direction === "left") - anchors.right = itemToStick.left; - else if (direction === "right") - anchors.left = itemToStick.right; - } - - width: 5 - height: parent.height - anchors.top: parent.top; - MouseArea - { - property int startX: 0; - anchors.fill: parent - onPressed: startX = mouseX; - onPositionChanged: - { - parent.x += mouseX; - var diff = 0; - if (direction == "left") - diff = mouseX - startX; - else if (direction == "right") - diff = -(mouseX - startX); - - if (itemMinimumWidth > itemToStick.width - diff) - { - brother.width = brother.width + diff; - itemToStick.width = itemMinimumWidth; - } - else - { - brother.width = brother.width + diff; - itemToStick.width = itemToStick.width - diff; - } - } - cursorShape: Qt.SizeHorCursor - } -} diff --git a/mix/res.qrc b/mix/res.qrc index 639881e6a..b511217e6 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -44,7 +44,6 @@ qml/BigIntValue.qml qml/js/QEtherHelper.js qml/js/TransactionHelper.js - qml/Splitter.qml qml/ContractLibrary.qml stdc/config.sol stdc/namereg.sol From 6a6917607b92c0b2a0d5c84683486033019d8341 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Feb 2015 18:09:14 +0100 Subject: [PATCH 12/17] fixed msvc build --- mix/AssemblyDebuggerControl.cpp | 1 - mix/MachineStates.h | 79 +++++++++++++++++++++++++++++++++ mix/MixClient.h | 41 +---------------- 3 files changed, 80 insertions(+), 41 deletions(-) create mode 100644 mix/MachineStates.h diff --git a/mix/AssemblyDebuggerControl.cpp b/mix/AssemblyDebuggerControl.cpp index e065513a8..7bf177981 100644 --- a/mix/AssemblyDebuggerControl.cpp +++ b/mix/AssemblyDebuggerControl.cpp @@ -20,7 +20,6 @@ #include #include #include -#include "AppContext.h" #include "ClientModel.h" #include "AssemblyDebuggerControl.h" diff --git a/mix/MachineStates.h b/mix/MachineStates.h new file mode 100644 index 000000000..d19fd9b74 --- /dev/null +++ b/mix/MachineStates.h @@ -0,0 +1,79 @@ +/* +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 . +*/ +/** @file MixClient.h +* @author Yann yann@ethdev.com +* @author Arkadiy Paronyan arkadiy@ethdev.com +* @date 2015 +* Ethereum IDE client. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace dev +{ +namespace mix +{ + + /** + * @brief Store information about a machine state. + */ + struct MachineState + { + uint64_t steps; + dev::Address address; + dev::u256 curPC; + dev::eth::Instruction inst; + dev::bigint newMemSize; + dev::u256 gas; + dev::u256s stack; + dev::bytes memory; + dev::bigint gasCost; + std::map storage; + std::vector levels; + unsigned codeIndex; + unsigned dataIndex; + }; + + /** + * @brief Store information about a machine states. + */ + struct ExecutionResult + { + ExecutionResult() : receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} + + std::vector machineStates; + std::vector transactionData; + std::vector executionCode; + bytes returnValue; + dev::Address address; + dev::Address sender; + dev::Address contractAddress; + dev::u256 value; + dev::eth::TransactionReceipt receipt; + }; + + using ExecutionResults = std::vector; +} +} \ No newline at end of file diff --git a/mix/MixClient.h b/mix/MixClient.h index dceb9ce7b..6118613ed 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -26,52 +26,13 @@ #include #include #include +#include "MachineStates.h" namespace dev { namespace mix { -/** - * @brief Store information about a machine state. - */ -struct MachineState -{ - uint64_t steps; - dev::Address address; - dev::u256 curPC; - dev::eth::Instruction inst; - dev::bigint newMemSize; - dev::u256 gas; - dev::u256s stack; - dev::bytes memory; - dev::bigint gasCost; - std::map storage; - std::vector levels; - unsigned codeIndex; - unsigned dataIndex; -}; - -/** - * @brief Store information about a machine states. - */ -struct ExecutionResult -{ - ExecutionResult(): receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {} - - std::vector machineStates; - std::vector transactionData; - std::vector executionCode; - bytes returnValue; - dev::Address address; - dev::Address sender; - dev::Address contractAddress; - dev::u256 value; - dev::eth::TransactionReceipt receipt; -}; - -using ExecutionResults = std::vector; - struct Block { ExecutionResults transactions; From 921e92474e71d6d1fc18eaa60640f7c2f3eb6c6f Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Feb 2015 18:20:43 +0100 Subject: [PATCH 13/17] reverted ethereum.js --- libjsqrc/ethereumjs/dist/ethereum.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libjsqrc/ethereumjs/dist/ethereum.js b/libjsqrc/ethereumjs/dist/ethereum.js index 5c912dbba..0f30280f9 100644 --- a/libjsqrc/ethereumjs/dist/ethereum.js +++ b/libjsqrc/ethereumjs/dist/ethereum.js @@ -903,8 +903,9 @@ var ProviderManager = function() { data.data._id = self.id; self.id++; var result = self.provider.send(data.data); - result = JSON.parse(result); - + + result = JSON.parse(result); + // dont call the callback if result is not an array, or empty one if (result.error || !(result.result instanceof Array) || result.result.length === 0) { return; @@ -1519,4 +1520,4 @@ module.exports = web3; },{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":8,"./lib/qtsync":9,"./lib/web3":12}]},{},["web3"]) -//# sourceMappingURL=ethereum.js.map +//# sourceMappingURL=ethereum.js.map \ No newline at end of file From ccb6b58e7185ec82b5d830c5812e1d04f5d5e45f Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Feb 2015 18:21:47 +0100 Subject: [PATCH 14/17] - Coding Standards. - Encode/Decode bigint behavior. --- mix/ClientModel.cpp | 3 --- mix/QVariableDefinition.cpp | 17 ++++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 93bcc7c92..a66335b5a 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -215,7 +215,6 @@ void ClientModel::executeSequence(std::vector const& _seque encoder.push(transaction.parameterValues.at(p)->encodeValue()); } - if (transaction.functionId.isEmpty()) { Address newAddress = deployContract(contractCode, transaction); @@ -226,9 +225,7 @@ void ClientModel::executeSequence(std::vector const& _seque } } else - { callContract(m_contractAddress, encoder.encodedData(), transaction); - } } onNewTransaction(); } diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index 5049283da..a76388d68 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -70,19 +70,18 @@ void QIntType::setValue(dev::bigint _value) dev::bytes QIntType::encodeValue() { dev::bigint i(value().toStdString()); - if (i < 0) - i = i + dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + 1; bytes ret(32); - toBigEndian(i, ret); + toBigEndian((u256)i, ret); return ret; } void QIntType::decodeValue(dev::bytes const& _rawValue) { - dev::bigint bigint = dev::fromBigEndian(_rawValue); - if (((bigint >> 32) & 1) == 1) - bigint = bigint - dev::bigint("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - 1; - setValue(bigint); + dev::u256 un = dev::fromBigEndian(_rawValue); + if (un >> 255) + setValue(-s256(~un + 1)); + else + setValue(un); } /* @@ -90,8 +89,8 @@ void QIntType::decodeValue(dev::bytes const& _rawValue) */ dev::bytes QHashType::encodeValue() { - QByteArray b = value().toUtf8(); - bytes r = bytes(b.begin(), b.end()); + QByteArray bytesAr = value().toLocal8Bit(); + bytes r = bytes(bytesAr.begin(), bytesAr.end()); return padded(r, 32); } From f0bfbf797a9bf13c92e164e34ba275af7e51645e Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Feb 2015 18:24:04 +0100 Subject: [PATCH 15/17] reverted some changes --- mix/main.cpp | 1 - mix/qml/ProjectList.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mix/main.cpp b/mix/main.cpp index b24b8a549..d0a19cfb5 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -36,7 +36,6 @@ int main(int _argc, char* _argv[]) //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 putenv((char*)"QT_QPA_PLATFORMTHEME="); putenv((char*)"QSG_RENDER_LOOP=threaded"); - putenv((char*)"QT_IM_MODULE="); #endif try { diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index e4e57455d..30f945706 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -3,7 +3,7 @@ import QtQuick.Window 2.0 import QtQuick.Layouts 1.0 import QtQuick.Controls 1.0 -Rectangle { +Item { property bool renameMode: false; ColumnLayout { anchors.fill: parent From d5e3f6f098f8c53b650b258df10643a502429f96 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Feb 2015 19:37:38 +0100 Subject: [PATCH 16/17] bug fixes --- libdevcore/CommonJS.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 9c20bdd53..980cb9081 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -60,15 +60,12 @@ bytes unpadded(bytes _b) bytes unpadLeft(bytes _b) { - int i = 0; + unsigned int i = 0; if (_b.size() == 0) return _b; - while (true) - if (_b.at(i) == byte(0)) - i++; - else - break; + while (i < _b.size() && _b[i] == byte(0)) + i++; if (i != 0) _b.erase(_b.begin(), _b.begin() + i); From 114db8ab36bc25e666702abdece63d607597b7d2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 2 Feb 2015 17:07:15 -0800 Subject: [PATCH 17/17] Revert State class changes for Mix. --- alethzero/MainWin.cpp | 7 ++++--- libethcore/CommonEth.cpp | 21 ++++++++++++++------ libethcore/CommonEth.h | 2 +- libethereum/Client.cpp | 7 +++---- libethereum/State.cpp | 41 ++++++++++++++++++---------------------- libethereum/State.h | 10 +++++----- mix/MixClient.cpp | 15 ++++++--------- mix/MixClient.h | 1 - test/stateOriginal.cpp | 7 ++++--- 9 files changed, 56 insertions(+), 55 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 3c87f649a..1921e80cd 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1209,8 +1209,9 @@ string Main::renderDiff(StateDiff const& _d) const if (ad.balance) { - s << "
" << indent << "Balance " << dec << formatBalance(ad.balance.to()); - s << " " << showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << noshowpos << ""; + s << "
" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]"; + auto d = (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())); + s << " " << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << ""; } if (ad.nonce) { @@ -1219,7 +1220,7 @@ string Main::renderDiff(StateDiff const& _d) const } if (ad.code) { - s << "
" << indent << "Code " << hex << ad.code.to().size() << " bytes"; + s << "
" << indent << "Code " << dec << ad.code.to().size() << " bytes"; if (ad.code.from().size()) s << " (" << ad.code.from().size() << " bytes)"; } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 8de20c21d..c530beef1 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -63,22 +63,31 @@ vector> const& units() return g_units; } -std::string formatBalance(u256 _b) +std::string formatBalance(bigint const& _b) { ostringstream ret; - if (_b > g_units[0].first * 10000) + u256 b; + if (_b < 0) { - ret << (_b / g_units[0].first) << " " << g_units[0].second; + ret << "-"; + b = (u256)-_b; + } + else + b = (u256)_b; + + if (b > g_units[0].first * 10000) + { + ret << (b / g_units[0].first) << " " << g_units[0].second; return ret.str(); } ret << setprecision(5); for (auto const& i: g_units) - if (i.first != 1 && _b >= i.first * 100) + if (i.first != 1 && b >= i.first * 100) { - ret << (double(_b / (i.first / 1000)) / 1000.0) << " " << i.second; + ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second; return ret.str(); } - ret << _b << " wei"; + ret << b << " wei"; return ret.str(); } diff --git a/libethcore/CommonEth.h b/libethcore/CommonEth.h index 704e354a2..966794953 100644 --- a/libethcore/CommonEth.h +++ b/libethcore/CommonEth.h @@ -39,7 +39,7 @@ extern const unsigned c_protocolVersion; extern const unsigned c_databaseVersion; /// User-friendly string representation of the amount _b in wei. -std::string formatBalance(u256 _b); +std::string formatBalance(bigint const& _b); /// Get information concerning the currency denominations. std::vector> const& units(); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index ccff335b6..9cfd18b2d 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -226,7 +226,7 @@ void Client::uninstallWatch(unsigned _i) void Client::noteChanged(h256Set const& _filters) { Guard l(m_filterLock); - cnote << "noteChanged(" << _filters << ")"; +// cnote << "noteChanged(" << _filters << ")"; // accrue all changes left in each filter into the watches. for (auto& i: m_watches) if (_filters.count(i.second.id)) @@ -361,13 +361,12 @@ void Client::setupState(State& _s) cwork << "SETUP MINE"; _s = m_postMine; } - _s.setUncles(m_bc); if (m_paranoia) { if (_s.amIJustParanoid(m_bc)) { cnote << "I'm just paranoid. Block is fine."; - _s.commitToMine(); + _s.commitToMine(m_bc); } else { @@ -375,7 +374,7 @@ void Client::setupState(State& _s) } } else - _s.commitToMine(); + _s.commitToMine(m_bc); } void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 831696beb..ecb5b2606 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -639,8 +639,7 @@ void State::uncommitToMine() bool State::amIJustParanoid(BlockChain const& _bc) { - setUncles(_bc); - commitToMine(); + commitToMine(_bc); // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); @@ -683,8 +682,20 @@ LogBloom State::logBloom() const return ret; } -void State::setUncles(BlockChain const& _bc) +void State::commitToMine(BlockChain const& _bc) { + uncommitToMine(); + +// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); +#ifdef ETH_PARANOIA + commit(); + cnote << "Pre-reward stateRoot:" << m_state.root(); +#endif + + m_lastTx = m_db; + + Addresses uncleAddresses; + RLPStream unclesData; unsigned unclesCount = 0; if (m_previousBlock != BlockChain::genesis()) @@ -703,26 +714,11 @@ void State::setUncles(BlockChain const& _bc) BlockInfo ubi(_bc.block(u)); ubi.streamRLP(unclesData, WithNonce); ++unclesCount; + uncleAddresses.push_back(ubi.coinbaseAddress); } } } - RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); - m_currentBlock.sha3Uncles = sha3(m_currentUncles); -} - -void State::commitToMine() -{ - uncommitToMine(); - -// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); -#ifdef ETH_PARANOIA - commit(); - cnote << "Pre-reward stateRoot:" << m_state.root(); -#endif - - m_lastTx = m_db; - MemoryDB tm; GenericTrieDB transactionsTrie(&tm); transactionsTrie.init(); @@ -752,13 +748,12 @@ void State::commitToMine() txs.swapOut(m_currentTxs); + RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); + m_currentBlock.transactionsRoot = transactionsTrie.root(); m_currentBlock.receiptsRoot = receiptsTrie.root(); m_currentBlock.logBloom = logBloom(); - - Addresses uncleAddresses; - for (const auto& r: RLP(m_currentUncles)) - uncleAddresses.push_back(BlockInfo::fromHeader(r.data()).coinbaseAddress); + m_currentBlock.sha3Uncles = sha3(m_currentUncles); // Apply rewards last of all. applyRewards(uncleAddresses); diff --git a/libethereum/State.h b/libethereum/State.h index 313cc5c44..0a288238d 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -105,16 +105,13 @@ public: /// @returns true if all is ok. If it's false, worry. bool amIJustParanoid(BlockChain const& _bc); - /// @brief Loads current block uncles from blockchain - void setUncles(BlockChain const& _bc); - /// Prepares the current state for mining. /// Commits all transactions into the trie, compiles uncles and transactions list, applies all /// rewards and populates the current block header with the appropriate hashes. /// The only thing left to do after this is to actually mine(). /// /// This may be called multiple times and without issue. - void commitToMine(); + void commitToMine(BlockChain const& _bc); /// Attempt to find valid nonce for block that this state represents. /// This function is thread-safe. You can safely have other interactions with this object while it is happening. @@ -125,11 +122,14 @@ public: /** Commit to DB and build the final block if the previous call to mine()'s result is completion. * Typically looks like: * @code + * while (notYetMined) + * { * // lock - * commitToMine(); + * commitToMine(_blockChain); // will call uncommitToMine if a repeat. * // unlock * MineInfo info; * for (info.complete = false; !info.complete; info = mine()) {} + * } * // lock * completeMine(); * // unlock diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 293d4036e..a6c833532 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -56,16 +56,15 @@ void MixClient::resetState(u256 _balance) genesis.state = m_state; Block open; m_blocks = Blocks { genesis, open }; //last block contains a list of pending transactions to be finalized - m_lastHashes.clear(); - m_lastHashes.resize(256); - m_lastHashes[0] = genesis.hash; +// m_lastHashes.clear(); +// m_lastHashes.resize(256); +// m_lastHashes[0] = genesis.hash; } void MixClient::executeTransaction(Transaction const& _t, State& _state) { bytes rlp = _t.rlp(); - - Executive execution(_state, m_lastHashes, 0); + Executive execution(_state, LastHashes(), 0); execution.setup(&rlp); std::vector machineStates; std::vector levels; @@ -165,14 +164,12 @@ void MixClient::mine() Block& block = m_blocks.back(); m_state.mine(0, true); m_state.completeMine(); - m_state.commitToMine(); + m_state.commitToMine(BlockChain()); + m_state.cleanup(true); block.state = m_state; block.info = m_state.info(); block.hash = block.info.hash; - m_state.cleanup(true); m_blocks.push_back(Block()); - m_lastHashes.insert(m_lastHashes.begin(), block.hash); - m_lastHashes.resize(256); h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; noteChanged(changed); diff --git a/mix/MixClient.h b/mix/MixClient.h index dceb9ce7b..fede1891e 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -145,7 +145,6 @@ private: std::map m_filters; std::map m_watches; Blocks m_blocks; - eth::LastHashes m_lastHashes; }; } diff --git a/test/stateOriginal.cpp b/test/stateOriginal.cpp index f4804c43b..b1a7c0d8e 100644 --- a/test/stateOriginal.cpp +++ b/test/stateOriginal.cpp @@ -51,7 +51,7 @@ int stateTest() cout << s; // Mine to get some ether! - s.commitToMine(); + s.commitToMine(bc); while (!s.mine(100).completed) {} s.completeMine(); bc.attemptImport(s.blockData(), stateDB); @@ -74,8 +74,9 @@ int stateTest() cout << s; // Mine to get some ether and set in stone. - s.commitToMine(); - while (!s.mine(100).completed) {} + s.commitToMine(bc); + s.commitToMine(bc); + while (!s.mine(50).completed) { s.commitToMine(bc); } s.completeMine(); bc.attemptImport(s.blockData(), stateDB);