Browse Source

Merge branch 'mix_srci' of http://github.com/arkpar/cpp-ethereum into mix_srci

cl-refactor
arkpar 10 years ago
parent
commit
626f686f56
  1. 6
      mix/AppContext.cpp
  2. 95
      mix/ClientModel.cpp
  3. 4
      mix/ClientModel.h
  4. 135
      mix/CodeModel.cpp
  5. 26
      mix/CodeModel.h
  6. 153
      mix/ContractCallDataEncoder.cpp
  7. 20
      mix/ContractCallDataEncoder.h
  8. 14
      mix/DebuggingStateWrapper.h
  9. 6
      mix/QBasicNodeDefinition.h
  10. 11
      mix/QContractDefinition.cpp
  11. 3
      mix/QContractDefinition.h
  12. 10
      mix/QFunctionDefinition.cpp
  13. 5
      mix/QFunctionDefinition.h
  14. 69
      mix/QVariableDeclaration.cpp
  15. 63
      mix/QVariableDeclaration.h
  16. 145
      mix/QVariableDefinition.cpp
  17. 86
      mix/QVariableDefinition.h
  18. 66
      mix/SolidityType.h
  19. 19
      mix/qml/DebugInfoList.qml
  20. 4
      mix/qml/Debugger.qml
  21. 7
      mix/qml/QBoolType.qml
  22. 10
      mix/qml/QBoolTypeView.qml
  23. 7
      mix/qml/QHashType.qml
  24. 6
      mix/qml/QHashTypeView.qml
  25. 7
      mix/qml/QIntType.qml
  26. 7
      mix/qml/QIntTypeView.qml
  27. 7
      mix/qml/QRealType.qml
  28. 7
      mix/qml/QStringType.qml
  29. 6
      mix/qml/QStringTypeView.qml
  30. 2
      mix/qml/StateDialog.qml
  31. 38
      mix/qml/StateListModel.qml
  32. 90
      mix/qml/StructView.qml
  33. 208
      mix/qml/TransactionDialog.qml
  34. 39
      mix/qml/VariablesView.qml
  35. 3
      mix/qml/html/WebContainer.html
  36. 8
      mix/qml/js/Debugger.js
  37. 7
      mix/res.qrc
  38. 26
      mix/stdc/std.sol

6
mix/AppContext.cpp

@ -68,14 +68,10 @@ 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<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");
qmlRegisterType<QBoolType>("org.ethereum.qml.QBoolType", 1, 0, "QBoolType");
qmlRegisterType<QVariableDeclaration>("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration");
qmlRegisterType<RecordLogEntry>("org.ethereum.qml.RecordLogEntry", 1, 0, "RecordLogEntry");
qmlRegisterType<SortFilterProxyModel>("org.ethereum.qml.SortFilterProxyModel", 1, 0, "SortFilterProxyModel");
qmlRegisterType<QSolidityType>("org.ethereum.qml.QSolidityType", 1, 0, "QSolidityType");
QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml"));
QObject* projectModel = projectModelComponent.create();
if (projectModelComponent.isError())

95
mix/ClientModel.cpp

@ -71,16 +71,11 @@ ClientModel::ClientModel(AppContext* _context):
m_context(_context), m_running(false), m_rpcConnector(new RpcConnector())
{
qRegisterMetaType<QBigInt*>("QBigInt*");
qRegisterMetaType<QIntType*>("QIntType*");
qRegisterMetaType<QStringType*>("QStringType*");
qRegisterMetaType<QRealType*>("QRealType*");
qRegisterMetaType<QHashType*>("QHashType*");
qRegisterMetaType<QEther*>("QEther*");
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*");
qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>");
qRegisterMetaType<QList<QVariableDeclaration*>>("QList<QVariableDeclaration*>");
qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*");
qRegisterMetaType<QSolidityType*>("QSolidityType*");
qRegisterMetaType<QMachineState*>("QMachineState");
qRegisterMetaType<QInstruction*>("QInstruction");
qRegisterMetaType<QCode*>("QCode");
@ -191,14 +186,8 @@ void ClientModel::setupState(QVariantMap _state)
{
if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later
contractId = m_context->codeModel()->contracts().keys()[0];
QVariantList qParams = transaction.value("qType").toList();
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString()));
for (QVariant const& variant: qParams)
{
QVariableDefinition* param = qvariant_cast<QVariableDefinition*>(variant);
transactionSettings.parameterValues.push_back(param);
}
transactionSettings.parameterValues = transaction.value("parameters").toMap();
if (contractId == functionId || functionId == "Constructor")
transactionSettings.functionId.clear();
@ -256,11 +245,11 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
if (!transaction.functionId.isEmpty())
encoder.encode(f);
for (int p = 0; p < transaction.parameterValues.size(); p++)
for (QVariableDeclaration const* p: f->parametersList())
{
if (f->parametersList().size() <= p || f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type())
BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(transaction.functionId.toStdString()));
encoder.push(transaction.parameterValues.at(p)->encodeValue());
QSolidityType const* type = p->type();
QVariant value = transaction.parameterValues.value(p->name());
encoder.encode(value, type->type());
}
if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId)
@ -347,9 +336,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
data.push_back(QMachineState::getDebugCallData(debugData, d));
QVariantList states;
QStringList solCallStack;
std::map<int, SolidityDeclaration> solLocals; //<stack pos, declaration>
QList<int> returnStack;
QVariantList solCallStack;
std::map<int, QVariableDeclaration*> solLocals; //<stack pos, decl>
std::map<QString, QVariableDeclaration*> storageDeclarations; //<name, decl>
unsigned prevInstructionIndex = 0;
for (MachineState const& s: _t.machineStates)
@ -366,44 +355,60 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
//register new local variable initialization
auto localIter = contract->locals().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
if (localIter != contract->locals().end())
solLocals[s.stack.size()] = localIter.value();
solLocals[s.stack.size()] = new QVariableDeclaration(debugData, localIter.value().name.toStdString(), localIter.value().type);
}
if (instruction.type() == dev::eth::Tag) //TODO: use annotations
if (instruction.type() == dev::eth::Tag)
{
//track calls into functions
AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
if (functionIter != contract->functions().end())
{
QString functionName = functionIter.value();
solCallStack.push_back(functionName);
returnStack.push_back(prevInstructionIndex + 1);
}
else if (!returnStack.empty() && instructionIndex == returnStack.back())
{
returnStack.pop_back();
if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
solCallStack.push_back(QVariant::fromValue(functionIter.value()));
else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty())
solCallStack.pop_back();
}
}
//format solidity context values
QStringList locals;
QVariantMap locals;
QVariantList localDeclarations;
QVariantMap localValues;
for(auto l: solLocals)
if (l.first < (int)s.stack.size())
locals.push_back(l.second.name + "\t" + formatValue(l.second.type, s.stack[l.first]));
{
localDeclarations.push_back(QVariant::fromValue(l.second));
localValues[l.second->name()] = formatValue(l.second->type()->type(), s.stack[l.first]);
}
locals["variables"] = localDeclarations;
locals["values"] = localValues;
QStringList storage;
QVariantMap storage;
QVariantList storageDeclarationList;
QVariantMap storageValues;
for(auto st: s.storage)
{
if (st.first < std::numeric_limits<unsigned>::max())
{
auto storageIter = contract->storage().find(static_cast<unsigned>(st.first));
if (storageIter != contract->storage().end())
storage.push_back(storageIter.value().name + "\t" + formatValue(storageIter.value().type, st.second));
{
QVariableDeclaration* storageDec = nullptr;
auto decIter = storageDeclarations.find(storageIter.value().name);
if (decIter != storageDeclarations.end())
storageDec = decIter->second;
else
{
storageDec = new QVariableDeclaration(debugData, storageIter.value().name.toStdString(), storageIter.value().type);
storageDeclarations[storageDec->name()] = storageDec;
}
storageDeclarationList.push_back(QVariant::fromValue(storageDec));
storageValues[storageDec->name()] = formatValue(storageDec->type()->type(), st.second);
}
}
storage["variables"] = storageDeclarationList;
storage["values"] = storageValues;
prevInstructionIndex = instructionIndex;
solState = new QSolState(debugData, storage, solCallStack, locals, instruction.getLocation().start, instruction.getLocation().end);
solState = new QSolState(debugData, std::move(storage), std::move(solCallStack), std::move(locals), instruction.getLocation().start, instruction.getLocation().end);
}
states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState)));
@ -413,9 +418,12 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
debugDataReady(debugData);
}
QString ClientModel::formatValue(SolidityType const&, dev::u256 const& _value)
QVariant ClientModel::formatValue(SolidityType const& _type, dev::u256 const& _value)
{
return QString::fromStdString(prettyU256(_value));
ContractCallDataEncoder decoder;
bytes val = toBigEndian(_value);
QVariant res = decoder.decode(_type, val);
return res;
}
void ClientModel::emptyRecord()
@ -526,9 +534,10 @@ void ClientModel::onNewTransaction()
{
function = funcDef->name();
ContractCallDataEncoder encoder;
QList<QVariableDefinition*> returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue);
for (auto const& var: returnValues)
returned += var->value() + " | ";
QStringList returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue);
returned += "(";
returned += returnValues.join(", ");
returned += ")";
}
}
}

4
mix/ClientModel.h

@ -63,7 +63,7 @@ struct TransactionSettings
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
QList<QVariableDefinition*> parameterValues;
QVariantMap parameterValues;
/// Standard contract url
QString stdContractUrl;
/// Sender
@ -199,7 +199,7 @@ private:
void onNewTransaction();
void onStateReset();
void showDebuggerForTransaction(ExecutionResult const& _t);
QString formatValue(SolidityType const& _type, dev::u256 const& _value);
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
AppContext* m_context;
std::atomic<bool> m_running;

135
mix/CodeModel.cpp

@ -49,62 +49,18 @@ const std::set<std::string> c_predefinedContracts =
namespace
{
using namespace dev::solidity;
class CollectDeclarationsVisitor: public ASTConstVisitor
{
public:
using namespace dev::solidity;
class CollectDeclarationsVisitor: public ASTConstVisitor
{
public:
CollectDeclarationsVisitor(QHash<LocationPair, QString>* _functions, QHash<LocationPair, SolidityDeclaration>* _locals, QHash<unsigned, SolidityDeclaration>* _storage):
m_functions(_functions), m_locals(_locals), m_storage(_storage), m_functionScope(false), m_storageSlot(0) {}
private:
QHash<LocationPair, QString>* m_functions;
QHash<LocationPair, SolidityDeclaration>* m_locals;
QHash<unsigned, SolidityDeclaration>* m_storage;
bool m_functionScope;
uint m_storageSlot;
private:
LocationPair nodeLocation(ASTNode const& _node)
{
return LocationPair(_node.getLocation().start, _node.getLocation().end);
}
SolidityType nodeType(Type const* _type)
{
if (!_type)
return SolidityType { SolidityType::Type::UnsignedInteger, 32 };
switch (_type->getCategory())
{
case Type::Category::Integer:
{
IntegerType const* it = dynamic_cast<IntegerType const*>(_type);
unsigned size = it->getNumBits() / 8;
SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger;
return SolidityType { typeCode, size };
}
case Type::Category::Bool:
return SolidityType { SolidityType::Type::Bool, _type->getSizeOnStack() * 32 };
case Type::Category::FixedBytes:
{
FixedBytesType const* s = dynamic_cast<FixedBytesType const*>(_type);
return SolidityType { SolidityType::Type::FixedBytes, static_cast<unsigned>(s->getNumBytes()) };
}
case Type::Category::Contract:
return SolidityType { SolidityType::Type::Address, _type->getSizeOnStack() * 32 };
case Type::Category::Array:
case Type::Category::Enum:
case Type::Category::Function:
case Type::Category::IntegerConstant:
case Type::Category::Magic:
case Type::Category::Mapping:
case Type::Category::Modifier:
case Type::Category::Real:
case Type::Category::Struct:
case Type::Category::TypeType:
case Type::Category::Void:
default:
return SolidityType { SolidityType::Type::UnsignedInteger, 32 };
}
}
virtual bool visit(FunctionDefinition const& _node)
{
m_functions->insert(nodeLocation(_node), QString::fromStdString(_node.getName()));
@ -120,7 +76,7 @@ namespace
virtual bool visit(VariableDeclaration const& _node)
{
SolidityDeclaration decl;
decl.type = nodeType(_node.getType().get());
decl.type = CodeModel::nodeType(_node.getType().get());
decl.name = QString::fromStdString(_node.getName());
if (m_functionScope)
m_locals->insert(nodeLocation(_node), decl);
@ -128,7 +84,14 @@ namespace
m_storage->insert(m_storageSlot++, decl);
return true;
}
};
private:
QHash<LocationPair, QString>* m_functions;
QHash<LocationPair, SolidityDeclaration>* m_locals;
QHash<unsigned, SolidityDeclaration>* m_storage;
bool m_functionScope;
uint m_storageSlot;
};
}
void BackgroundWorker::queueCodeChange(int _jobId)
@ -142,8 +105,9 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
{
std::string name = _contractName.toStdString();
auto const& contractDefinition = _compiler.getContractDefinition(name);
m_contract.reset(new QContractDefinition(&contractDefinition));
m_contract.reset(new QContractDefinition(nullptr, &contractDefinition));
QQmlEngine::setObjectOwnership(m_contract.get(), QQmlEngine::CppOwnership);
m_contract->moveToThread(QApplication::instance()->thread());
m_bytes = _compiler.getBytecode(_contractName.toStdString());
m_assemblyItems = _compiler.getRuntimeAssemblyItems(name);
m_constructorAssemblyItems = _compiler.getAssemblyItems(name);
@ -344,3 +308,70 @@ dev::bytes const& CodeModel::getStdContractCode(const QString& _contractName, co
return m_compiledContracts.at(_contractName);
}
SolidityType CodeModel::nodeType(solidity::Type const* _type)
{
SolidityType r { SolidityType::Type::UnsignedInteger, 32, false, false, QString::fromStdString(_type->toString()), std::vector<SolidityDeclaration>(), std::vector<QString>() };
if (!_type)
return r;
r.dynamicSize = _type->isDynamicallySized();
switch (_type->getCategory())
{
case Type::Category::Integer:
{
IntegerType const* it = dynamic_cast<IntegerType const*>(_type);
r.size = it->getNumBits() / 8;
r.type = it->isAddress() ? SolidityType::Type::Address : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger;
}
break;
case Type::Category::Bool:
r.type = SolidityType::Type::Bool;
break;
case Type::Category::FixedBytes:
{
FixedBytesType const* b = dynamic_cast<FixedBytesType const*>(_type);
r.type = SolidityType::Type::Bytes;
r.size = static_cast<unsigned>(b->getNumBytes());
}
case Type::Category::Contract:
r.type = SolidityType::Type::Address;
break;
case Type::Category::Array:
{
ArrayType const* array = dynamic_cast<ArrayType const*>(_type);
if (array->isByteArray())
r.type = SolidityType::Type::Bytes;
else
r = nodeType(array->getBaseType().get());
r.array = true;
}
break;
case Type::Category::Enum:
{
r.type = SolidityType::Type::Enum;
EnumType const* e = dynamic_cast<EnumType const*>(_type);
for(auto const& enumValue: e->getEnumDefinition().getMembers())
r.enumNames.push_back(QString::fromStdString(enumValue->getName()));
}
break;
case Type::Category::Struct:
{
r.type = SolidityType::Type::Struct;
StructType const* s = dynamic_cast<StructType const*>(_type);
for(auto const& structMember: s->getMembers())
r.members.push_back(SolidityDeclaration { QString::fromStdString(structMember.first), nodeType(structMember.second.get()) });
}
break;
case Type::Category::Function:
case Type::Category::IntegerConstant:
case Type::Category::Magic:
case Type::Category::Mapping:
case Type::Category::Modifier:
case Type::Category::Real:
case Type::Category::TypeType:
case Type::Category::Void:
default:
break;
}
return r;
}

26
mix/CodeModel.h

@ -31,6 +31,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/Guards.h>
#include <libevmcore/Assembly.h>
#include "SolidityType.h"
class QTextDocument;
@ -39,7 +40,8 @@ namespace dev
namespace solidity
{
class CompilerStack;
class CompilerStack;
class Type;
}
namespace mix
@ -66,26 +68,6 @@ private:
using LocationPair = QPair<int, int>;
struct SolidityType
{
enum class Type //TODO: arrays and structs
{
SignedInteger,
UnsignedInteger,
Bool,
Address,
FixedBytes,
};
Type type;
unsigned size; //bytes
};
struct SolidityDeclaration
{
QString name;
SolidityType type;
};
///Compilation result model. Contains all the compiled contract data required by UI
class CompiledContract: public QObject
{
@ -165,6 +147,8 @@ public:
Q_INVOKABLE CompiledContract* contractByDocumentId(QString _documentId) const;
/// Reset code model
Q_INVOKABLE void reset() { reset(QVariantMap()); }
/// Convert solidity type info to mix type
static SolidityType nodeType(solidity::Type const* _type);
signals:
/// Emited on compilation state change

153
mix/ContractCallDataEncoder.cpp

@ -35,7 +35,9 @@ using namespace dev::mix;
bytes ContractCallDataEncoder::encodedData()
{
return m_encodedData;
bytes r(m_encodedData);
r.insert(r.end(), m_dynamicData.begin(), m_dynamicData.end());
return r;
}
void ContractCallDataEncoder::encode(QFunctionDefinition const* _function)
@ -44,38 +46,149 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function)
m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end());
}
void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const& _type)
{
if (_type.dynamicSize)
{
u256 count = 0;
if (_type.type == SolidityType::Type::Bytes)
count = encodeSingleItem(_data, _type, m_dynamicData);
else
{
QVariantList list = qvariant_cast<QVariantList>(_data);
for (auto const& item: list)
encodeSingleItem(item, _type, m_dynamicData);
count = list.size();
}
bytes sizeEnc(32);
toBigEndian(count, sizeEnc);
m_encodedData.insert(m_encodedData.end(), sizeEnc.begin(), sizeEnc.end());
}
else
encodeSingleItem(_data, _type, m_encodedData);
}
unsigned ContractCallDataEncoder::encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest)
{
if (_type.type == SolidityType::Type::Struct)
BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Struct parameters are not supported yet"));
unsigned const alignSize = 32;
QString src = _data.toString();
bytes result;
if (src.length() >= 2 && ((src.startsWith("\"") && src.endsWith("\"")) || (src.startsWith("\'") && src.endsWith("\'"))))
{
src = src.remove(src.length() - 1, 1).remove(0, 1);
QByteArray bytesAr = src.toLocal8Bit();
result = bytes(bytesAr.begin(), bytesAr.end());
}
else if (src.startsWith("0x"))
{
result = fromHex(src.toStdString().substr(2));
if (_type.type != SolidityType::Type::Bytes)
result = padded(result, alignSize);
}
else
{
bigint i(src.toStdString());
result = bytes(alignSize);
toBigEndian((u256)i, result);
}
unsigned dataSize = _type.dynamicSize ? result.size() : alignSize;
_dest.insert(_dest.end(), result.begin(), result.end());
if (_dest.size() % alignSize != 0)
_dest.resize((_dest.size() & ~(alignSize - 1)) + alignSize);
return dataSize;
}
void ContractCallDataEncoder::push(bytes const& _b)
{
m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end());
}
QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const& _returnParameters, bytes _value)
bigint ContractCallDataEncoder::decodeInt(dev::bytes const& _rawValue)
{
dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue);
if (un >> 255)
return (-s256(~un + 1));
return un;
}
QString ContractCallDataEncoder::toString(dev::bigint const& _int)
{
std::stringstream str;
str << std::dec << _int;
return QString::fromStdString(str.str());
}
dev::bytes ContractCallDataEncoder::encodeBool(QString const& _str)
{
bytes b(1);
b[0] = _str == "1" || _str.toLower() == "true " ? 1 : 0;
return padded(b, 32);
}
bool ContractCallDataEncoder::decodeBool(dev::bytes const& _rawValue)
{
byte ret = _rawValue.at(_rawValue.size() - 1);
return (ret != 0);
}
QString ContractCallDataEncoder::toString(bool _b)
{
return _b ? "true" : "false";
}
dev::bytes ContractCallDataEncoder::encodeBytes(QString const& _str)
{
QByteArray bytesAr = _str.toLocal8Bit();
bytes r = bytes(bytesAr.begin(), bytesAr.end());
return padded(r, 32);
}
dev::bytes ContractCallDataEncoder::decodeBytes(dev::bytes const& _rawValue)
{
return _rawValue;
}
QString ContractCallDataEncoder::toString(dev::bytes const& _b)
{
return QString::fromStdString(dev::toJS(_b));
}
QVariant ContractCallDataEncoder::decode(SolidityType const& _type, bytes const& _value)
{
bytesConstRef value(&_value);
bytes rawParam(32);
QList<QVariableDefinition*> r;
for (int k = 0; k <_returnParameters.length(); k++)
{
QVariableDeclaration* dec = static_cast<QVariableDeclaration*>(_returnParameters.at(k));
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("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());
value.populate(&rawParam);
QSolidityType::Type type = _type.type;
if (type == QSolidityType::Type::SignedInteger || type == QSolidityType::Type::UnsignedInteger || type == QSolidityType::Type::Address)
return QVariant::fromValue(toString(decodeInt(rawParam)));
else if (type == QSolidityType::Type::Bool)
return QVariant::fromValue(toString(decodeBool(rawParam)));
else if (type == QSolidityType::Type::Bytes || type == QSolidityType::Type::Hash)
return QVariant::fromValue(toString(decodeBytes(rawParam)));
else if (type == QSolidityType::Type::Struct)
return QVariant::fromValue(QString("struct")); //TODO
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found"));
}
QStringList ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const& _returnParameters, bytes _value)
{
bytesConstRef value(&_value);
bytes rawParam(32);
QStringList r;
for (int k = 0; k <_returnParameters.length(); k++)
{
value.populate(&rawParam);
def->decodeValue(rawParam);
r.push_back(def);
value = value.cropped(32);
qDebug() << "decoded return value : " << dec->type() << " " << def->value();
QVariableDeclaration* dec = static_cast<QVariableDeclaration*>(_returnParameters.at(k));
SolidityType const& type = dec->type()->type();
r.append(decode(type, rawParam).toString());
}
return r;
}

20
mix/ContractCallDataEncoder.h

@ -33,6 +33,7 @@ namespace mix
class QFunctionDefinition;
class QVariableDeclaration;
class QVariableDefinition;
class QSolidityType;
/**
* @brief Encode/Decode data to be sent to a transaction or to be displayed in a view.
@ -43,15 +44,32 @@ public:
ContractCallDataEncoder() {}
/// Encode hash of the function to call.
void encode(QFunctionDefinition const* _function);
/// Encode data for corresponding type
void encode(QVariant const& _data, SolidityType const& _type);
/// Decode variable in order to be sent to QML view.
QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> const& _dec, bytes _value);
QStringList decode(QList<QVariableDeclaration*> const& _dec, bytes _value);
/// Decode single variable
QVariant decode(SolidityType const& _type, bytes const& _value);
/// Get all encoded data encoded by encode function.
bytes encodedData();
/// Push the given @a _b to the current param context.
void push(bytes const& _b);
private:
unsigned encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest);
bigint decodeInt(dev::bytes const& _rawValue);
dev::bytes encodeInt(QString const& _str);
QString toString(dev::bigint const& _int);
dev::bytes encodeBool(QString const& _str);
bool decodeBool(dev::bytes const& _rawValue);
QString toString(bool _b);
dev::bytes encodeBytes(QString const& _str);
dev::bytes decodeBytes(dev::bytes const& _rawValue);
QString toString(dev::bytes const& _b);
private:
bytes m_encodedData;
bytes m_dynamicData;
};
}

14
mix/DebuggingStateWrapper.h

@ -60,21 +60,21 @@ private:
class QSolState: public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList storage MEMBER m_storage CONSTANT)
Q_PROPERTY(QStringList callStack MEMBER m_callStack CONSTANT)
Q_PROPERTY(QStringList locals MEMBER m_locals CONSTANT)
Q_PROPERTY(QVariantMap storage MEMBER m_storage CONSTANT)
Q_PROPERTY(QVariantList callStack MEMBER m_callStack CONSTANT)
Q_PROPERTY(QVariantMap locals MEMBER m_locals CONSTANT)
Q_PROPERTY(int start MEMBER m_start CONSTANT)
Q_PROPERTY(int end MEMBER m_end CONSTANT)
public:
QSolState(QObject* _parent, QStringList const& _storage, QStringList const& _callStack, QStringList const& _locals, int _start, int _end):
QSolState(QObject* _parent, QVariantMap&& _storage, QVariantList&& _callStack, QVariantMap&& _locals, int _start, int _end):
QObject(_parent), m_storage(_storage), m_callStack(_callStack), m_locals(_locals), m_start(_start), m_end(_end)
{ }
private:
QStringList m_storage;
QStringList m_callStack;
QStringList m_locals;
QVariantMap m_storage;
QVariantList m_callStack;
QVariantMap m_locals;
int m_start;
int m_end;
};

6
mix/QBasicNodeDefinition.h

@ -35,10 +35,10 @@ class QBasicNodeDefinition: public QObject
Q_PROPERTY(QString name READ name CONSTANT)
public:
QBasicNodeDefinition(): QObject() {}
QBasicNodeDefinition(QObject* _parent = nullptr): QObject(_parent) {}
~QBasicNodeDefinition() {}
QBasicNodeDefinition(solidity::Declaration const* _d): QObject(), m_name(QString::fromStdString(_d->getName())) {}
QBasicNodeDefinition(std::string const& _name): QObject(), m_name(QString::fromStdString(_name)) {}
QBasicNodeDefinition(QObject* _parent, solidity::Declaration const* _d): QObject(_parent), m_name(QString::fromStdString(_d->getName())) {}
QBasicNodeDefinition(QObject* _parent, std::string const& _name): QObject(_parent), m_name(QString::fromStdString(_name)) {}
/// Get the name of the node.
QString name() const { return m_name; }

11
mix/QContractDefinition.cpp

@ -32,16 +32,17 @@
using namespace dev::solidity;
using namespace dev::mix;
QContractDefinition::QContractDefinition(dev::solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_contract)
QContractDefinition::QContractDefinition(QObject* _parent, dev::solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_parent, _contract)
{
QObject* parent = _parent ? _parent : this;
if (_contract->getConstructor() != nullptr)
m_constructor = new QFunctionDefinition(ContractType(*_contract).getConstructorType());
m_constructor = new QFunctionDefinition(parent, ContractType(*_contract).getConstructorType());
else
m_constructor = new QFunctionDefinition();
m_constructor = new QFunctionDefinition(parent);
for (auto const& it: _contract->getInterfaceFunctions())
m_functions.append(new QFunctionDefinition(it.second));}
m_functions.append(new QFunctionDefinition(parent, it.second));
}
QFunctionDefinition const* QContractDefinition::getFunction(dev::FixedHash<4> _hash) const
{

3
mix/QContractDefinition.h

@ -39,8 +39,7 @@ class QContractDefinition: public QBasicNodeDefinition
Q_PROPERTY(dev::mix::QFunctionDefinition* constructor READ constructor CONSTANT)
public:
QContractDefinition() {}
QContractDefinition(solidity::ContractDefinition const* _contract);
QContractDefinition(QObject* _parent, solidity::ContractDefinition const* _contract);
/// Get all the functions of the contract.
QQmlListProperty<QFunctionDefinition> functions() const { return QQmlListProperty<QFunctionDefinition>(const_cast<QContractDefinition*>(this), const_cast<QContractDefinition*>(this)->m_functions); }
/// Get the constructor of the contract.

10
mix/QFunctionDefinition.cpp

@ -28,15 +28,15 @@
using namespace dev::solidity;
using namespace dev::mix;
QFunctionDefinition::QFunctionDefinition(dev::solidity::FunctionTypePointer const& _f): QBasicNodeDefinition(&_f->getDeclaration()), m_hash(dev::sha3(_f->getCanonicalSignature()))
QFunctionDefinition::QFunctionDefinition(QObject* _parent, dev::solidity::FunctionTypePointer const& _f): QBasicNodeDefinition(_parent, &_f->getDeclaration()), m_hash(dev::sha3(_f->getCanonicalSignature()))
{
auto paramNames = _f->getParameterNames();
auto paramTypes = _f->getParameterTypeNames();
auto paramTypes = _f->getParameterTypes();
auto returnNames = _f->getReturnParameterNames();
auto returnTypes = _f->getReturnParameterTypeNames();
auto returnTypes = _f->getReturnParameterTypes();
for (unsigned i = 0; i < paramNames.size(); ++i)
m_parameters.append(new QVariableDeclaration(paramNames[i], paramTypes[i]));
m_parameters.append(new QVariableDeclaration(_parent, paramNames[i], paramTypes[i].get()));
for (unsigned i = 0; i < returnNames.size(); ++i)
m_returnParameters.append(new QVariableDeclaration(returnNames[i], returnTypes[i]));
m_returnParameters.append(new QVariableDeclaration(_parent, returnNames[i], returnTypes[i].get()));
}

5
mix/QFunctionDefinition.h

@ -38,8 +38,9 @@ class QFunctionDefinition: public QBasicNodeDefinition
Q_PROPERTY(QQmlListProperty<dev::mix::QVariableDeclaration> parameters READ parameters)
public:
QFunctionDefinition() {}
QFunctionDefinition(solidity::FunctionTypePointer const& _f);
QFunctionDefinition(){}
QFunctionDefinition(QObject* _parent): QBasicNodeDefinition(_parent) {}
QFunctionDefinition(QObject* _parent, solidity::FunctionTypePointer const& _f);
/// Get all input parameters of this function.
QList<QVariableDeclaration*> const& parametersList() const { return m_parameters; }
/// Get all input parameters of this function as QML property.

69
mix/QVariableDeclaration.cpp

@ -0,0 +1,69 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDeclaration.app
* @author Yann yann@ethdev.com
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
*/
#include "QVariableDeclaration.h"
#include "CodeModel.h"
namespace dev
{
namespace mix
{
QVariableDeclaration::QVariableDeclaration(QObject* _parent, solidity::VariableDeclaration const* _v):
QBasicNodeDefinition(_parent, _v),
m_type(new QSolidityType(this, CodeModel::nodeType(_v->getType().get())))
{
}
QVariableDeclaration::QVariableDeclaration(QObject* _parent, std::string const& _name, SolidityType const& _type):
QBasicNodeDefinition(_parent, _name),
m_type(new QSolidityType(_parent, _type))
{
}
QVariableDeclaration::QVariableDeclaration(QObject* _parent, std::string const& _name, solidity::Type const* _type):
QBasicNodeDefinition(_parent, _name),
m_type(new QSolidityType(this, CodeModel::nodeType(_type)))
{
}
QSolidityType::QSolidityType(QObject* _parent, SolidityType const& _type):
QObject(_parent),
m_type(_type)
{
}
QVariantList QSolidityType::members() const
{
QVariantList members;
if (m_type.type == Type::Struct)
for (auto const& structMember: m_type.members)
members.push_back(QVariant::fromValue(new QVariableDeclaration(parent(), structMember.name.toStdString(), structMember.type)));
if (m_type.type == Type::Enum)
for (auto const& enumName: m_type.enumNames)
members.push_back(QVariant::fromValue(enumName));
return members;
}
}
}

63
mix/QVariableDeclaration.h

@ -20,34 +20,77 @@
*/
#include <QDebug>
#include <QStringList>
#include <libsolidity/AST.h>
#include <QVariantList>
#include "QBasicNodeDefinition.h"
#include "SolidityType.h"
#pragma once
namespace solidity
{
class Type;
class VariableDeclaration;
}
namespace dev
{
namespace mix
{
/// UI wrapper around solidity type
class QSolidityType: public QObject
{
Q_OBJECT
Q_PROPERTY(int category READ category CONSTANT) //qml does not support enum properties
Q_PROPERTY(int size READ size CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QVariantList members READ members CONSTANT)
public:
QSolidityType() {}
QSolidityType(QObject* _parent, SolidityType const& _type);
using Type = SolidityType::Type;
enum QmlType //TODO: Q_ENUMS does not support enum forwarding. Keep in sync with SolidityType::Type
{
SignedInteger,
UnsignedInteger,
Hash,
Bool,
Address,
Bytes,
Enum,
Struct
};
Q_ENUMS(QmlType)
SolidityType const& type() const { return m_type; }
Type category() const { return m_type.type; }
int size() const { return m_type.size; }
QString name() const { return m_type.name; }
QVariantList members() const;
private:
SolidityType m_type;
};
/// UI wrapper around declaration (name + type)
class QVariableDeclaration: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QString type READ type WRITE setType)
Q_PROPERTY(QSolidityType* type READ type CONSTANT)
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; }
QVariableDeclaration(QObject* _parent, solidity::VariableDeclaration const* _v);
QVariableDeclaration(QObject* _parent, std::string const& _name, SolidityType const& _type);
QVariableDeclaration(QObject* _parent, std::string const& _name, solidity::Type const* _type);
QSolidityType* type() const { return m_type; }
void setType(QSolidityType* _type) { m_type = _type; }
private:
QString m_type;
QSolidityType* m_type;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*)

145
mix/QVariableDefinition.cpp

@ -1,145 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libdevcore/CommonData.h>
#include <libethcore/CommonJS.h>
#include "QVariableDefinition.h"
using namespace dev::mix;
int QVariableDefinitionList::rowCount(const QModelIndex& _parent) const
{
Q_UNUSED(_parent);
return m_def.size();
}
QVariant QVariableDefinitionList::data(const QModelIndex& _index, int _role) const
{
if (_role != Qt::DisplayRole)
return QVariant();
int i = _index.row();
if (i < 0 || i >= m_def.size())
return QVariant(QVariant::Invalid);
return QVariant::fromValue(m_def.at(i));
}
QHash<int, QByteArray> QVariableDefinitionList::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "variable";
return roles;
}
QVariableDefinition* QVariableDefinitionList::val(int _idx)
{
if (_idx < 0 || _idx >= m_def.size())
return nullptr;
return m_def.at(_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());
bytes ret(32);
toBigEndian((u256)i, ret);
return ret;
}
void QIntType::decodeValue(dev::bytes const& _rawValue)
{
dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue);
if (un >> 255)
setValue(-s256(~un + 1));
else
setValue(un);
}
/*
* QHashType
*/
dev::bytes QHashType::encodeValue()
{
QByteArray bytesAr = value().toLocal8Bit();
bytes r = bytes(bytesAr.begin(), bytesAr.end());
return padded(r, 32);
}
void QHashType::decodeValue(dev::bytes const& _rawValue)
{
std::string _ret = asString(unpadLeft(_rawValue));
setValue(QString::fromStdString(_ret));
}
/*
* QRealType
*/
dev::bytes QRealType::encodeValue()
{
return bytes();
}
void QRealType::decodeValue(dev::bytes const& _rawValue)
{
Q_UNUSED(_rawValue);
}
/*
* QStringType
*/
dev::bytes QStringType::encodeValue()
{
QByteArray b = value().toUtf8();
bytes r = bytes(b.begin(), b.end());
return paddedRight(r, 32);
}
void QStringType::decodeValue(dev::bytes const& _rawValue)
{
setValue(QString::fromUtf8((char*)_rawValue.data()));
}
/*
* QBoolType
*/
dev::bytes QBoolType::encodeValue()
{
return padded(jsToBytes(value().toStdString()), 32);
}
void QBoolType::decodeValue(dev::bytes const& _rawValue)
{
byte ret = _rawValue.at(_rawValue.size() - 1);
bool boolRet = (ret == byte(1));
m_boolValue = boolRet;
m_value = m_boolValue ? "1" : "0";
}

86
mix/QVariableDefinition.h

@ -63,95 +63,9 @@ private:
QVariableDeclaration* m_dec;
};
class QVariableDefinitionList: public QAbstractListModel
{
Q_OBJECT
public:
QVariableDefinitionList(QList<QVariableDefinition*> _def): m_def(_def) {}
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
/// Return the variable definition at index _idx.
QVariableDefinition* val(int _idx);
/// Return the list of variables.
QList<QVariableDefinition*> def() { return m_def; }
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(dev::bytes const& _rawValue) override;
/// @returns an instance of QBigInt for the current 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
{
Q_OBJECT
public:
QRealType() {}
QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QStringType: public QVariableDefinition
{
Q_OBJECT
public:
QStringType() {}
QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QHashType: public QVariableDefinition
{
Q_OBJECT
public:
QHashType() {}
QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QBoolType: public QVariableDefinition
{
Q_OBJECT
public:
QBoolType(): m_boolValue(false) {}
QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value), m_boolValue(false) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
/// @returns the boolean value for the current definition.
bool toBool() { return m_boolValue; }
private:
bool m_boolValue;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QIntType*)
Q_DECLARE_METATYPE(dev::mix::QStringType*)
Q_DECLARE_METATYPE(dev::mix::QHashType*)
Q_DECLARE_METATYPE(dev::mix::QBoolType*)

66
mix/SolidityType.h

@ -0,0 +1,66 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file SolidityType.h
* @author Yann yann@ethdev.com
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#pragma once
#include <QString>
#include <vector>
namespace dev
{
namespace mix
{
struct SolidityDeclaration;
//Type info extracted from solidity AST
struct SolidityType
{
enum Type //keep in sync with QSolidity::Type
{
SignedInteger,
UnsignedInteger,
Hash, //TODO: remove
Bool,
Address,
Bytes,
Enum,
Struct
};
Type type;
unsigned size; //in bytes,
bool array;
bool dynamicSize;
QString name;
std::vector<SolidityDeclaration> members; //for struct
std::vector<QString> enumNames; //for enum
};
struct SolidityDeclaration
{
QString name;
SolidityType type;
};
}
}

19
mix/qml/DebugInfoList.qml

@ -11,6 +11,8 @@ ColumnLayout {
property bool enableSelection: false;
property real storedHeight: 0;
property Component itemDelegate
property Component componentDelegate
property alias item: loader.item
signal rowActivated(int index)
spacing: 0
@ -91,15 +93,25 @@ ColumnLayout {
}
}
]
TableView {
clip: true;
alternatingRowColors: false
Loader
{
id: loader
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 3
anchors.leftMargin: 3
width: parent.width - 3
height: parent.height - 6
sourceComponent: componentDelegate ? componentDelegate : table
}
Component
{
id: table
TableView
{
clip: true;
alternatingRowColors: false
anchors.fill: parent
model: listModel
selectionMode: enableSelection ? SelectionMode.SingleSelection : SelectionMode.NoSelection
headerDelegate: null
@ -131,4 +143,5 @@ ColumnLayout {
}
}
}
}
}

4
mix/qml/Debugger.qml

@ -574,7 +574,7 @@ Rectangle {
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
visible: !assemblyMode
StorageView {
VariablesView {
title : qsTr("Locals")
anchors.fill: parent
id: solLocals
@ -589,7 +589,7 @@ Rectangle {
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
visible: !assemblyMode
StorageView {
VariablesView {
title : qsTr("Members")
anchors.fill: parent
id: solStorage

7
mix/qml/QBoolType.qml

@ -1,7 +0,0 @@
import QtQuick 2.0
import org.ethereum.qml.QBoolType 1.0
QBoolType
{
}

10
mix/qml/QBoolTypeView.qml

@ -4,8 +4,10 @@ import QtQuick.Controls 1.3
Item
{
id: editRoot
property string text
property string value
property string defaultValue
height: 20
width: 150
Rectangle {
anchors.fill: parent
@ -14,10 +16,10 @@ Item
property bool inited: false
Component.onCompleted:
{
if (text === "")
if (value === "")
currentIndex = parseInt(defaultValue);
else
currentIndex = parseInt(text);
currentIndex = parseInt(value);
inited = true
}
@ -26,7 +28,7 @@ Item
onCurrentIndexChanged:
{
if (inited)
text = comboModel.get(currentIndex).value;
value = comboModel.get(currentIndex).value;
}
model: ListModel
{

7
mix/qml/QHashType.qml

@ -1,7 +0,0 @@
import QtQuick 2.0
import org.ethereum.qml.QHashType 1.0
QHashType
{
}

6
mix/qml/QHashTypeView.qml

@ -2,8 +2,10 @@ import QtQuick 2.0
Item
{
property alias text: textinput.text
property alias value: textinput.text
id: editRoot
height: 20
width: 150
SourceSansProBold
{
@ -16,7 +18,7 @@ Item
color: "#f7f7f7"
TextInput {
id: textinput
text: text
text: value
anchors.fill: parent
wrapMode: Text.WrapAnywhere
clip: true

7
mix/qml/QIntType.qml

@ -1,7 +0,0 @@
import QtQuick 2.0
import org.ethereum.qml.QIntType 1.0
QIntType
{
}

7
mix/qml/QIntTypeView.qml

@ -1,9 +1,12 @@
import QtQuick 2.0
import QtQuick.Layouts 1.1
Item
{
property alias text: textinput.text
property alias value: textinput.text
id: editRoot
height: 20
width: 150
SourceSansProBold
{
@ -16,7 +19,7 @@ Item
color: "#f7f7f7"
TextInput {
id: textinput
text: text
text: value
anchors.fill: parent
font.family: boldFont.name
clip: true

7
mix/qml/QRealType.qml

@ -1,7 +0,0 @@
import QtQuick 2.0
import org.ethereum.qml.QRealType 1.0
QRealType
{
}

7
mix/qml/QStringType.qml

@ -1,7 +0,0 @@
import QtQuick 2.0
import org.ethereum.qml.QStringType 1.0
QStringType
{
}

6
mix/qml/QStringTypeView.qml

@ -2,8 +2,10 @@ import QtQuick 2.0
Item
{
property alias text: textinput.text
property alias value: textinput.text
id: editRoot
height: 20
width: 150
SourceSansProBold
{
@ -16,7 +18,7 @@ Item
color: "#f7f7f7"
TextInput {
id: textinput
text: text
text: value
clip: true
anchors.fill: parent
wrapMode: Text.WrapAnywhere

2
mix/qml/StateDialog.qml

@ -373,7 +373,7 @@ Window {
{
iconSource: "qrc:/qml/img/edit.png"
action: editAction
visible: !stdContract
visible: stdContract === false
width: 10
height: 10
Action {

38
mix/qml/StateListModel.qml

@ -41,38 +41,13 @@ Item {
value: QEtherHelper.createEther(t.value.value, t.value.unit),
gas: QEtherHelper.createBigInt(t.gas.value),
gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit),
stdContract: t.stdContract,
stdContract: t.stdContract ? true : false,
parameters: {},
sender: t.sender
};
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");
else {
console.log("Unknown parameter type: " + type);
continue;
}
r.parameters[key] = t.parameters[key];
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;
}
@ -118,14 +93,7 @@ Item {
parameters: {}
};
for (var key in t.parameters)
{
var param = {
name: key,
value: t.parameters[key],
type: getParamType(key, t.qType)
}
r.parameters[key] = param;
}
r.parameters[key] = t.parameters[key];
return r;
}

90
mix/qml/StructView.qml

@ -0,0 +1,90 @@
import QtQuick 2.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.ethereum.qml.QSolidityType 1.0
Column
{
id: root
property alias members: repeater.model //js array
property var value : { x: "333" }
Layout.fillWidth: true
Repeater
{
id: repeater
visible: model.length > 0
Layout.fillWidth: true
RowLayout
{
id: row
height: 20 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0)
Layout.fillWidth: true
DefaultLabel {
height: 20
id: typeLabel
text: modelData.type.name
Layout.preferredWidth: 50
}
DefaultLabel {
id: nameLabel
text: modelData.name
Layout.preferredWidth: 80
}
DefaultLabel {
id: equalLabel
text: "="
Layout.preferredWidth: 15
}
Loader
{
id: typeLoader
Layout.preferredWidth: 150
sourceComponent:
{
var t = modelData.type.category;
if (t === QSolidityType.SignedInteger || t === QSolidityType.UnsignedInteger)
return Qt.createComponent("qrc:/qml/QIntTypeView.qml");
else if (t === QSolidityType.Bool)
return Qt.createComponent("qrc:/qml/QBoolTypeView.qml");
else if (t === QSolidityType.Bytes)
return Qt.createComponent("qrc:/qml/QStringTypeView.qml");
else if (t === QSolidityType.Hash || t === QSolidityType.Address)
return Qt.createComponent("qrc:/qml/QHashTypeView.qml");
else if (t === QSolidityType.Struct)
return Qt.createComponent("qrc:/qml/StructView.qml");
else
return undefined;
}
onLoaded:
{
var ptype = members[index].type;
var pname = members[index].name;
var vals = value;
if (ptype.category === QSolidityType.Struct && !item.members) {
item.value = getValue();
item.members = ptype.members;
}
else
item.value = getValue();
item.onValueChanged.connect(function() {
vals[pname] = item.value;
valueChanged();
});
}
function getValue()
{
if (value && value[modelData.name] !== undefined)
return value[modelData.name];
else if (modelData.type.category === QSolidityType.Struct)
return {};
return "";
}
}
}
}
}

208
mix/qml/TransactionDialog.qml

@ -11,26 +11,23 @@ Window {
id: modalTransactionDialog
modality: Qt.ApplicationModal
width: 520
height: (paramsModel.count > 0 ? 500 : 300)
height: 500;
visible: false
color: StateDialogStyle.generic.backgroundColor
title: qsTr("Edit Transaction")
property int transactionIndex
property alias transactionParams: paramsModel;
property alias gas: gasValueEdit.gasValue;
property alias gasPrice: gasPriceField.value;
property alias transactionValue: valueField.value;
property string contractId: contractComboBox.currentValue();
property alias functionId: functionComboBox.currentText;
property var itemParams;
property var paramValues;
property var paramsModel: [];
property bool useTransactionDefaultValue: false
property var qType;
property alias stateAccounts: senderComboBox.model
signal accepted;
function open(index, item) {
qType = [];
rowFunction.visible = !useTransactionDefaultValue;
rowValue.visible = !useTransactionDefaultValue;
rowGas.visible = !useTransactionDefaultValue;
@ -44,7 +41,7 @@ Window {
var functionId = item.functionId;
rowFunction.visible = true;
itemParams = item.parameters !== undefined ? item.parameters : {};
paramValues = item.parameters !== undefined ? item.parameters : {};
if (item.sender)
senderComboBox.select(item.sender);
@ -73,15 +70,15 @@ Window {
functionComboBox.currentIndex = functionIndex;
paramsModel.clear();
paramsModel = [];
if (functionId !== contractComboBox.currentValue())
loadParameters();
else {
var contract = codeModel.contracts[contractId];
if (contract) {
var parameters = contract.contract.constructor.parameters;
for (var p = 0; p < parameters.length; p++)
loadParameter(parameters[p]);
var params = contract.contract.constructor.parameters;
for (var p = 0; p < params.length; p++)
loadParameter(params[p]);
}
}
modalTransactionDialog.setX((Screen.width - width) / 2);
@ -89,6 +86,9 @@ Window {
visible = true;
valueField.focus = true;
modalTransactionDialog.height = (paramsModel.length > 0 ? 500 : 300);
paramLabel.visible = paramsModel.length > 0;
paramScroll.visible = paramsModel.length > 0;
}
function loadFunctions(contractId)
@ -110,32 +110,11 @@ Window {
{
var type = parameter.type;
var pname = parameter.name;
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(modalTransactionDialog);
var value = itemParams[pname] !== undefined ? itemParams[pname] : "";
param.setValue(value);
param.setDeclaration(parameter);
qType.push({ name: pname, value: param });
paramsModel.append({ name: pname, type: type, value: value });
paramsModel.push({ name: pname, type: type });
}
function loadParameters() {
paramsModel.clear();
if (!paramsModel)
return;
paramsModel = []
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var contract = codeModel.contracts[contractComboBox.currentValue()];
if (contract) {
@ -147,15 +126,11 @@ Window {
}
}
}
}
typeLoader.value = {}
typeLoader.members = []
typeLoader.value = paramValues;
typeLoader.members = paramsModel;
function param(name)
{
for (var k = 0; k < paramsModel.count; k++)
{
if (paramsModel.get(k).name === name)
return paramsModel.get(k);
}
}
function close()
@ -163,15 +138,6 @@ Window {
visible = false;
}
function qTypeParam(name)
{
for (var k in qType)
{
if (qType[k].name === name)
return qType[k].value;
}
}
function getItem()
{
var item;
@ -194,15 +160,7 @@ Window {
}
item.sender = senderComboBox.model[senderComboBox.currentIndex].secret;
var orderedQType = [];
for (var p = 0; p < transactionDialog.transactionParams.count; p++) {
var parameter = transactionDialog.transactionParams.get(p);
var qtypeParam = qTypeParam(parameter.name);
qtypeParam.setValue(parameter.value);
orderedQType.push(qtypeParam);
item.parameters[parameter.name] = parameter.value;
}
item.qType = orderedQType;
item.parameters = paramValues;
return item;
}
@ -370,145 +328,27 @@ Window {
id: paramLabel
text: qsTr("Parameters:")
Layout.preferredWidth: 75
visible: paramsModel.count > 0
}
ScrollView
{
id: paramScroll
anchors.top: paramLabel.bottom
anchors.topMargin: 10
Layout.preferredWidth: 350
Layout.fillHeight: true
visible: paramsModel.count > 0
Column
{
id: paramRepeater
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 3
Repeater
{
height: 20 * paramsModel.count
model: paramsModel
visible: paramsModel.count > 0
RowLayout
{
id: row
Layout.fillWidth: true
height: 20
DefaultLabel {
id: typeLabel
text: type
Layout.preferredWidth: 50
}
DefaultLabel {
id: nameLabel
text: name
Layout.preferredWidth: 80
}
DefaultLabel {
id: equalLabel
text: "="
Layout.preferredWidth: 15
}
Loader
StructView
{
id: typeLoader
Layout.preferredWidth: 150
function getCurrent()
{
return modalTransactionDialog.param(name);
}
Connections {
target: typeLoader.item
onTextChanged: {
typeLoader.getCurrent().value = typeLoader.item.text;
}
}
sourceComponent:
{
if (type.indexOf("int") !== -1)
return intViewComp;
else if (type.indexOf("bool") !== -1)
return boolViewComp;
else if (type.indexOf("string") !== -1)
return stringViewComp;
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
return hashViewComp;
else
return null;
}
Component
{
id: intViewComp
QIntTypeView
{
height: 20
width: 150
id: intView
text: typeLoader.getCurrent().value
}
}
Component
{
id: boolViewComp
QBoolTypeView
{
height: 20
width: 150
id: boolView
defaultValue: "1"
Component.onCompleted:
{
var current = typeLoader.getCurrent().value;
(current === "" ? text = defaultValue : text = current);
}
}
}
Component
{
id: stringViewComp
QStringTypeView
{
height: 20
width: 150
id: stringView
text:
{
return typeLoader.getCurrent().value
}
}
}
Component
{
id: hashViewComp
QHashTypeView
{
height: 20
width: 150
id: hashView
text: typeLoader.getCurrent().value
}
}
}
}
}
members: paramsModel;
}
}
CommonSeparator
{
Layout.fillWidth: true
visible: paramsModel.count > 0
visible: paramsModel.length > 0
}
}
@ -530,8 +370,4 @@ Window {
}
}
}
ListModel {
id: paramsModel
}
}

39
mix/qml/VariablesView.qml

@ -0,0 +1,39 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import "."
DebugInfoList
{
id: storage
collapsible: true
title : qsTr("Storage")
componentDelegate: structComp
Component
{
id: structComp
ScrollView
{
property alias members: typeLoader.members;
property alias value: typeLoader.value;
anchors.fill: parent
StructView
{
id: typeLoader
members: []
value: {}
Layout.preferredWidth: parent.width
}
}
}
function setData(members, values) {
storage.item.value = {};
storage.item.members = [];
storage.item.value = values; //TODO: use a signal for this?
storage.item.members = members;
}
}

3
mix/qml/html/WebContainer.html

@ -20,7 +20,8 @@ updateContracts = function(contracts) {
window.web3.reset();
window.contracts = {};
for (var c in contracts) {
var contract = window.web3.eth.contract(contracts[c].address, contracts[c].interface);
var contractProto = window.web3.eth.contract(contracts[c].interface);
var contract = new contractProto(contracts[c].address);
window.contracts[c] = {
address: c.address,
interface: c.interface,

8
mix/qml/js/Debugger.js

@ -199,12 +199,12 @@ function completeCtxInformation(state)
storage.listModel = state.debugStorage;
memoryDump.listModel = state.debugMemory;
if (state.solidity) {
solLocals.listModel = state.solidity.locals;
solStorage.listModel = state.solidity.storage;
solLocals.setData(state.solidity.locals.variables, state.solidity.locals.values);
solStorage.setData(state.solidity.storage.variables, state.solidity.storage.values);
solCallStack.listModel = state.solidity.callStack;
} else {
solLocals.listModel = [];
solStorage.listModel = [];
solLocals.setData([], {});
solStorage.setData([], {});
solCallStack.listModel = [];
}
}

7
mix/res.qrc

@ -44,13 +44,8 @@
<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>
<file>qml/js/QEtherHelper.js</file>
<file>qml/js/TransactionHelper.js</file>
<file>qml/QStringType.qml</file>
<file>qml/QBoolTypeView.qml</file>
<file>qml/QIntTypeView.qml</file>
<file>qml/QRealTypeView.qml</file>
@ -115,6 +110,8 @@
<file>qml/img/copy.png</file>
<file>qml/img/broom.png</file>
<file>qml/LogsPaneStyle.qml</file>
<file>qml/StructView.qml</file>
<file>qml/img/console.png</file>
<file>qml/VariablesView.qml</file>
</qresource>
</RCC>

26
mix/stdc/std.sol

@ -13,14 +13,12 @@ contract Config is mortal {
if (tx.origin != owner)
return;
services[id] = service;
log1(0, id);
}
function unregister(uint id) {
if (msg.sender != owner && services[id] != msg.sender)
return;
services[id] = address(0);
log1(0, id);
}
function lookup(uint service) constant returns(address a) {
@ -56,8 +54,8 @@ web3.eth.contract(addrConfig, abiConfig).lookup(1).call().then(function(r){ addr
// Gav Wood <g@ethdev.com>
contract NameRegister {
function getAddress(string32 _name) constant returns (address o_owner) {}
function getName(address _owner) constant returns (string32 o_name) {}
function getAddress(bytes32 _name) constant returns (address o_owner) {}
function getName(address _owner) constant returns (bytes32 o_name) {}
}
contract NameReg is owned, NameRegister {
@ -68,11 +66,9 @@ contract NameReg is owned, NameRegister {
toName[this] = "NameReg";
toAddress["NameReg"] = this;
Config(addrConfig).register(1, this);
log1(0, hash256(addrConfig));
log1(0, hash256(this));
}
function register(string32 name) {
function register(bytes32 name) {
// Don't allow the same name to be overwritten.
if (toAddress[name] != address(0))
return;
@ -82,41 +78,39 @@ contract NameReg is owned, NameRegister {
toName[msg.sender] = name;
toAddress[name] = msg.sender;
log1(0, hash256(msg.sender));
}
function unregister() {
string32 n = toName[msg.sender];
bytes32 n = toName[msg.sender];
if (n == "")
return;
log1(0, hash256(toAddress[n]));
toName[msg.sender] = "";
toAddress[n] = address(0);
}
function addressOf(string32 name) constant returns (address addr) {
function addressOf(bytes32 name) constant returns (address addr) {
return toAddress[name];
}
function nameOf(address addr) constant returns (string32 name) {
function nameOf(address addr) constant returns (bytes32 name) {
return toName[addr];
}
mapping (address => string32) toName;
mapping (string32 => address) toAddress;
mapping (address => bytes32) toName;
mapping (bytes32 => address) toAddress;
}
/*
// Solidity Interface:
contract NameReg{function kill(){}function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}}
contract NameReg{function kill(){}function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}}
// Example Solidity use:
NameReg(addrNameReg).register("Some Contract");
// JS Interface:
var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"string32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"string32"}]},{"constant":false,"inputs":[{"name":"name","type":"string32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}];
var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"bytes32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"bytes32"}]},{"constant":false,"inputs":[{"name":"name","type":"bytes32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}];
// Example JS use:
web3.eth.contract(addrNameReg, abiNameReg).register("My Name").transact();

Loading…
Cancel
Save