From ef7561b16e611d0fbe797ad763380061370183cf Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Jan 2015 14:36:46 +0100 Subject: [PATCH 01/11] - 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/11] 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/11] - 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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 ccb6b58e7185ec82b5d830c5812e1d04f5d5e45f Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Feb 2015 18:21:47 +0100 Subject: [PATCH 10/11] - 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 d5e3f6f098f8c53b650b258df10643a502429f96 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Feb 2015 19:37:38 +0100 Subject: [PATCH 11/11] 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);