Browse Source

- Manage solidity parameter types

cl-refactor
yann300 10 years ago
committed by yann300
parent
commit
ef7561b16e
  1. 5
      mix/AppContext.cpp
  2. 21
      mix/ClientModel.cpp
  3. 2
      mix/ClientModel.h
  4. 115
      mix/ContractCallDataEncoder.cpp
  5. 12
      mix/ContractCallDataEncoder.h
  6. 1
      mix/QBigInt.h
  7. 2
      mix/QFunctionDefinition.cpp
  8. 11
      mix/QVariableDeclaration.h
  9. 130
      mix/QVariableDefinition.cpp
  10. 74
      mix/QVariableDefinition.h
  11. 5
      mix/qml.qrc
  12. 8
      mix/qml/QBoolType.qml
  13. 8
      mix/qml/QHashType.qml
  14. 8
      mix/qml/QIntType.qml
  15. 8
      mix/qml/QRealType.qml
  16. 13
      mix/qml/QVariableDefinition.qml
  17. 44
      mix/qml/TransactionDialog.qml

5
mix/AppContext.cpp

@ -71,6 +71,11 @@ void AppContext::load()
m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get());
qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther");
qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt");
//qmlRegisterType<QVariableDefinition>("org.ethereum.qml.QVariableDefinition", 1, 0, "QVariableDefinition");
qmlRegisterType<QIntType>("org.ethereum.qml.QIntType", 1, 0, "QIntType");
qmlRegisterType<QRealType>("org.ethereum.qml.QRealType", 1, 0, "QRealType");
qmlRegisterType<QStringType>("org.ethereum.qml.QStringType", 1, 0, "QStringType");
qmlRegisterType<QHashType>("org.ethereum.qml.QHashType", 1, 0, "QHashType");
QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml"));
QObject* projectModel = projectModelComponent.create();
if (projectModelComponent.isError())

21
mix/ClientModel.cpp

@ -42,6 +42,10 @@ ClientModel::ClientModel(AppContext* _context):
m_context(_context), m_running(false)
{
qRegisterMetaType<QBigInt*>("QBigInt*");
qRegisterMetaType<QIntType*>("QIntType*");
qRegisterMetaType<QStringType*>("QStringType*");
qRegisterMetaType<QRealType*>("QRealType*");
qRegisterMetaType<QHashType*>("QHashType*");
qRegisterMetaType<QEther*>("QEther*");
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("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<QEther*>(p.value()))->toU256Wei()));
{
QVariableDefinition* param = qvariant_cast<QVariableDefinition*>(p.value());
transactionSettings.parameterValues.push_back(param);
}
transactionSequence.push_back(transactionSettings);
}
executeSequence(transactionSequence, balance);
@ -123,15 +129,8 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> 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());
}

2
mix/ClientModel.h

@ -54,7 +54,7 @@ struct TransactionSettings
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
std::map<QString, u256> parameterValues;
QList<QVariableDefinition*> parameterValues;
};

115
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<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> _returnParameters, bytes _value)
@ -74,37 +57,79 @@ QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDecla
for (int k = 0; k <_returnParameters.length(); k++)
{
QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k);
int padding = this->padding(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)

12
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<QVariableDefinition*> decode(QList<QVariableDeclaration*> _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);
};
}

1
mix/QBigInt.h

@ -28,6 +28,7 @@
#include <QQmlEngine>
#include <libdevcore/CommonJS.h>
#include <libdevcore/Common.h>
#include "QVariableDefinition.h"
using namespace dev;

2
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<std::shared_ptr<VariableDeclaration>> returnParameters = _f->getReturnParameters();
for (unsigned i = 0; i < returnParameters.size(); i++)
m_returnParameters.append(new QVariableDeclaration(returnParameters.at(i).get()));

11
mix/QVariableDeclaration.h

@ -19,6 +19,7 @@
* @date 2014
*/
#include <QStringList>
#include <libsolidity/AST.h>
#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;
};

130
mix/QVariableDefinition.cpp

@ -19,6 +19,7 @@
* @date 2014
*/
#include <libdevcore/CommonJS.h>
#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));
}

74
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<QVariableDefinition*> 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*)

5
mix/qml.qrc

@ -43,5 +43,10 @@
<file>qml/Ether.qml</file>
<file>qml/EtherValue.qml</file>
<file>qml/BigIntValue.qml</file>
<file>qml/QVariableDefinition.qml</file>
<file>qml/QBoolType.qml</file>
<file>qml/QHashType.qml</file>
<file>qml/QIntType.qml</file>
<file>qml/QRealType.qml</file>
</qresource>
</RCC>

8
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"
}

8
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"
}

8
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"
}

8
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"
}

13
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
}

44
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;
}

Loading…
Cancel
Save