Browse Source

array formatting fixes

cl-refactor
arkpar 10 years ago
parent
commit
b98ef3b354
  1. 115
      mix/ClientModel.cpp
  2. 1
      mix/ClientModel.h
  3. 45
      mix/CodeModel.cpp
  4. 4
      mix/CodeModel.h
  5. 2
      mix/MixClient.cpp
  6. 5
      mix/QVariableDeclaration.h
  7. 6
      mix/SolidityType.h

115
mix/ClientModel.cpp

@ -43,6 +43,7 @@
using namespace dev;
using namespace dev::eth;
using namespace std;
namespace dev
{
@ -54,7 +55,7 @@ class RpcConnector: public jsonrpc::AbstractServerConnector
public:
virtual bool StartListening() override { return true; }
virtual bool StopListening() override { return true; }
virtual bool SendResponse(std::string const& _response, void*) override
virtual bool SendResponse(string const& _response, void*) override
{
m_response = QString::fromStdString(_response);
return true;
@ -101,7 +102,7 @@ QString ClientModel::apiCall(QString const& _message)
}
catch (...)
{
std::cerr << boost::current_exception_diagnostic_information();
cerr << boost::current_exception_diagnostic_information();
return QString();
}
}
@ -125,7 +126,7 @@ void ClientModel::mine()
catch (...)
{
m_mining = false;
std::cerr << boost::current_exception_diagnostic_information();
cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
emit miningStateChanged();
@ -142,7 +143,7 @@ QVariantMap ClientModel::contractAddresses() const
{
QVariantMap res;
for (auto const& c: m_contractAddresses)
res.insert(c.first, QString::fromStdString(dev::toJS(c.second)));
res.insert(c.first, QString::fromStdString(toJS(c.second)));
return res;
}
@ -151,14 +152,14 @@ void ClientModel::setupState(QVariantMap _state)
QVariantList balances = _state.value("accounts").toList();
QVariantList transactions = _state.value("transactions").toList();
std::map<Secret, u256> accounts;
map<Secret, u256> accounts;
for (auto const& b: balances)
{
QVariantMap address = b.toMap();
accounts.insert(std::make_pair(Secret(address.value("secret").toString().toStdString()), (qvariant_cast<QEther*>(address.value("balance")))->toU256Wei()));
accounts.insert(make_pair(Secret(address.value("secret").toString().toStdString()), (qvariant_cast<QEther*>(address.value("balance")))->toU256Wei()));
}
std::vector<TransactionSettings> transactionSequence;
vector<TransactionSettings> transactionSequence;
for (auto const& t: transactions)
{
QVariantMap transaction = t.toMap();
@ -196,7 +197,7 @@ void ClientModel::setupState(QVariantMap _state)
executeSequence(transactionSequence, accounts);
}
void ClientModel::executeSequence(std::vector<TransactionSettings> const& _sequence, std::map<Secret, u256> const& _balances)
void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, map<Secret, u256> const& _balances)
{
if (m_running)
BOOST_THROW_EXCEPTION(ExecutionStateException());
@ -218,7 +219,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
if (!transaction.stdContractUrl.isEmpty())
{
//std contract
dev::bytes const& stdContractCode = m_codeModel->getStdContractCode(transaction.contractId, transaction.stdContractUrl);
bytes const& stdContractCode = m_codeModel->getStdContractCode(transaction.contractId, transaction.stdContractUrl);
TransactionSettings stdTransaction = transaction;
stdTransaction.gas = 500000;// TODO: get this from std contracts library
Address address = deployContract(stdContractCode, stdTransaction);
@ -231,7 +232,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
CompiledContract const& compilerRes = m_codeModel->contract(transaction.contractId);
QFunctionDefinition const* f = nullptr;
bytes contractCode = compilerRes.bytes();
std::shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract();
shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract();
if (transaction.functionId.isEmpty())
f = contractDef->constructor();
else
@ -290,12 +291,12 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
}
catch(boost::exception const&)
{
std::cerr << boost::current_exception_diagnostic_information();
cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
catch(std::exception const& e)
catch(exception const& e)
{
std::cerr << boost::current_exception_diagnostic_information();
cerr << boost::current_exception_diagnostic_information();
emit runFailed(e.what());
}
m_running = false;
@ -322,7 +323,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
{
QHash<int, int> codeMap;
codes.push_back(QMachineState::getHumanReadableCode(debugData, code.address, code.code, codeMap));
codeMaps.push_back(std::move(codeMap));
codeMaps.push_back(move(codeMap));
//try to resolve contract for source level debugging
auto nameIter = m_contractNames.find(code.address);
if (nameIter != m_contractNames.end())
@ -330,7 +331,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
CompiledContract const& compilerRes = m_codeModel->contract(nameIter->second);
eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes.assemblyItems() : compilerRes.constructorAssemblyItems();
codes.back()->setDocument(compilerRes.documentId());
codeItems.push_back(std::move(assemblyItems));
codeItems.push_back(move(assemblyItems));
contracts.push_back(&compilerRes);
}
else
@ -346,8 +347,8 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
QVariantList states;
QVariantList solCallStack;
std::map<int, QVariableDeclaration*> solLocals; //<stack pos, decl>
std::map<QString, QVariableDeclaration*> storageDeclarations; //<name, decl>
map<int, QVariableDeclaration*> solLocals; //<stack pos, decl>
map<QString, QVariableDeclaration*> storageDeclarations; //<name, decl>
unsigned prevInstructionIndex = 0;
for (MachineState const& s: _t.machineStates)
@ -359,7 +360,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
CompiledContract const* contract = contracts[s.codeIndex];
AssemblyItem const& instruction = codeItems[s.codeIndex][instructionIndex];
if (instruction.type() == dev::eth::Push && !instruction.data())
if (instruction.type() == eth::Push && !instruction.data())
{
//register new local variable initialization
auto localIter = contract->locals().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
@ -367,7 +368,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
solLocals[s.stack.size()] = new QVariableDeclaration(debugData, localIter.value().name.toStdString(), localIter.value().type);
}
if (instruction.type() == dev::eth::Tag)
if (instruction.type() == eth::Tag)
{
//track calls into functions
AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
@ -382,7 +383,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
QVariantMap locals;
QVariantList localDeclarations;
QVariantMap localValues;
for(auto l: solLocals)
for (auto l: solLocals)
if (l.first < (int)s.stack.size())
{
if (l.second->type()->name().startsWith("mapping"))
@ -396,42 +397,45 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
QVariantMap storage;
QVariantList storageDeclarationList;
QVariantMap storageValues;
for(auto st: s.storage)
if (st.first < std::numeric_limits<unsigned>::max())
for (auto st: s.storage)
if (st.first < numeric_limits<unsigned>::max())
{
auto storageIter = contract->storage().find(static_cast<unsigned>(st.first));
if (storageIter != contract->storage().end())
{
QVariableDeclaration* storageDec = nullptr;
auto decIter = storageDeclarations.find(storageIter.value().name);
if (decIter != storageDeclarations.end())
storageDec = decIter->second;
else
for (SolidityDeclaration const& codeDec : storageIter.value())
{
storageDec = new QVariableDeclaration(debugData, storageIter.value().name.toStdString(), storageIter.value().type);
storageDeclarations[storageDec->name()] = storageDec;
if (codeDec.type.name.startsWith("mapping"))
continue; //mapping type not yet managed
auto decIter = storageDeclarations.find(codeDec.name);
if (decIter != storageDeclarations.end())
storageDec = decIter->second;
else
{
storageDec = new QVariableDeclaration(debugData, codeDec.name.toStdString(), codeDec.type);
storageDeclarations[storageDec->name()] = storageDec;
}
storageDeclarationList.push_back(QVariant::fromValue(storageDec));
storageValues[storageDec->name()] = formatStorageValue(storageDec->type()->type(), s.storage, codeDec.offset, codeDec.slot);
}
if (storageDec->type()->name().startsWith("mapping"))
break; //mapping type not yet managed
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, std::move(storage), std::move(solCallStack), std::move(locals), instruction.getLocation().start, instruction.getLocation().end, QString::fromUtf8(instruction.getLocation().sourceName->c_str()));
solState = new QSolState(debugData, move(storage), move(solCallStack), move(locals), instruction.getLocation().start, instruction.getLocation().end, QString::fromUtf8(instruction.getLocation().sourceName->c_str()));
}
states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState)));
}
debugData->setStates(std::move(states));
debugData->setStates(move(states));
debugDataReady(debugData);
}
QVariant ClientModel::formatValue(SolidityType const& _type, dev::u256 const& _value)
QVariant ClientModel::formatValue(SolidityType const& _type, u256 const& _value)
{
ContractCallDataEncoder decoder;
bytes val = toBigEndian(_value);
@ -439,6 +443,41 @@ QVariant ClientModel::formatValue(SolidityType const& _type, dev::u256 const& _v
return res;
}
QVariant ClientModel::formatStorageValue(SolidityType const& _type, map<u256, u256> const& _storage, unsigned _offset, u256 const& _slot)
{
u256 slot = _slot;
QVariantList values;
ContractCallDataEncoder decoder;
u256 count = 1;
if (_type.dynamicSize)
{
count = _storage.at(slot);
slot = fromBigEndian<u256>(sha3(toBigEndian(slot)).asBytes());
}
else if (_type.array)
count = _type.count;
unsigned offset = _offset;
while (count--)
{
bytes slotBytes = toBigEndian(_storage.at(slot));
bytes val(slotBytes.begin() + offset, slotBytes.begin() + offset + _type.size);
values.append(decoder.decode(_type, val));
offset += _type.size;
if ((offset + _type.size) > 32)
{
slot++;
offset = 0;
}
}
if (!_type.array)
return values[0];
return QVariant::fromValue(values);
}
void ClientModel::emptyRecord()
{
debugDataReady(new QDebugData());
@ -464,9 +503,9 @@ void ClientModel::callContract(Address const& _contract, bytes const& _data, Tra
RecordLogEntry* ClientModel::lastBlock() const
{
eth::BlockInfo blockInfo = m_client->blockInfo();
std::stringstream strGas;
stringstream strGas;
strGas << blockInfo.gasUsed;
std::stringstream strNumber;
stringstream strNumber;
strNumber << blockInfo.number;
RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash.ref()))), tr("Gas Used: ") + QString::fromStdString(strGas.str()), QString(), QString(), false, RecordLogEntry::RecordType::Block);
QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership);
@ -489,7 +528,7 @@ void ClientModel::onNewTransaction()
unsigned recordIndex = tr.executonIndex;
QString transactionIndex = tr.isCall() ? QObject::tr("Call") : QString("%1:%2").arg(block).arg(tr.transactionIndex);
QString address = QString::fromStdString(toJS(tr.address));
QString value = QString::fromStdString(dev::toString(tr.value));
QString value = QString::fromStdString(toString(tr.value));
QString contract = address;
QString function;
QString returned;

1
mix/ClientModel.h

@ -200,6 +200,7 @@ private:
void onStateReset();
void showDebuggerForTransaction(ExecutionResult const& _t);
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
QVariant formatStorageValue(SolidityType const& _type, std::map<dev::u256, dev::u256> const& _storage, unsigned _offset, dev::u256 const& _slot);
std::atomic<bool> m_running;
std::atomic<bool> m_mining;

45
mix/CodeModel.cpp

@ -54,8 +54,8 @@ 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) {}
CollectDeclarationsVisitor(QHash<LocationPair, QString>* _functions, QHash<LocationPair, SolidityDeclaration>* _locals):
m_functions(_functions), m_locals(_locals), m_functionScope(false) {}
private:
LocationPair nodeLocation(ASTNode const& _node)
{
@ -79,19 +79,17 @@ private:
SolidityDeclaration decl;
decl.type = CodeModel::nodeType(_node.getType().get());
decl.name = QString::fromStdString(_node.getName());
decl.slot = 0;
decl.offset = 0;
if (m_functionScope)
m_locals->insert(nodeLocation(_node), decl);
else
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;
};
dev::eth::AssemblyItems filterLocations(dev::eth::AssemblyItems const& _locations, dev::solidity::ContractDefinition const& _contract, QHash<LocationPair, QString> _functions)
@ -108,6 +106,24 @@ dev::eth::AssemblyItems filterLocations(dev::eth::AssemblyItems const& _location
return result;
}
QHash<unsigned, SolidityDeclarations> collectStorage(dev::solidity::ContractDefinition const& _contract)
{
QHash<unsigned, SolidityDeclarations> result;
dev::solidity::ContractType const* contractType = dynamic_cast<dev::solidity::ContractType const*>(_contract.getType(nullptr).get());
if (!contractType)
return result;
for (auto v : contractType->getStateVariables())
{
dev::solidity::VariableDeclaration const* declaration = std::get<0>(v);
dev::u256 slot = std::get<1>(v);
unsigned offset = std::get<2>(v);
result[static_cast<unsigned>(slot)].push_back(SolidityDeclaration { QString::fromStdString(declaration->getName()), CodeModel::nodeType(declaration->getType().get()), slot, offset });
}
return result;
}
} //namespace
void BackgroundWorker::queueCodeChange(int _jobId)
@ -133,7 +149,8 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
if (contractDefinition.getLocation().sourceName.get())
m_documentId = QString::fromStdString(*contractDefinition.getLocation().sourceName);
CollectDeclarationsVisitor visitor(&m_functions, &m_locals, &m_storage);
CollectDeclarationsVisitor visitor(&m_functions, &m_locals);
m_storage = collectStorage(contractDefinition);
contractDefinition.accept(visitor);
m_assemblyItems = filterLocations(_compiler.getRuntimeAssemblyItems(name), contractDefinition, m_functions);
m_constructorAssemblyItems = filterLocations(_compiler.getAssemblyItems(name), contractDefinition, m_functions);
@ -335,7 +352,7 @@ dev::bytes const& CodeModel::getStdContractCode(const QString& _contractName, co
SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
{
SolidityType r { SolidityType::Type::UnsignedInteger, 32, false, false, QString::fromStdString(_type->toString()), std::vector<SolidityDeclaration>(), std::vector<QString>() };
SolidityType r { SolidityType::Type::UnsignedInteger, 32, 1, false, false, QString::fromStdString(_type->toString()), std::vector<SolidityDeclaration>(), std::vector<QString>() };
if (!_type)
return r;
r.dynamicSize = _type->isDynamicallySized();
@ -367,7 +384,12 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
if (array->isByteArray())
r.type = SolidityType::Type::Bytes;
else
r = nodeType(array->getBaseType().get());
{
SolidityType elementType = nodeType(array->getBaseType().get());
elementType.name = r.name;
r = elementType;
}
r.count = static_cast<unsigned>(array->getLength());
r.array = true;
}
break;
@ -384,7 +406,10 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
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()) });
{
auto slotAndOffset = s->getStorageOffsetsOfMember(structMember.first);
r.members.push_back(SolidityDeclaration { QString::fromStdString(structMember.first), nodeType(structMember.second.get()), slotAndOffset.first, slotAndOffset.second });
}
}
break;
case Type::Category::Function:

4
mix/CodeModel.h

@ -99,7 +99,7 @@ public:
QHash<LocationPair, QString> const& functions() const { return m_functions; }
QHash<LocationPair, SolidityDeclaration> const& locals() const { return m_locals; }
QHash<unsigned, SolidityDeclaration> const& storage() const { return m_storage; }
QHash<unsigned, SolidityDeclarations> const& storage() const { return m_storage; }
private:
uint m_sourceHash;
@ -112,7 +112,7 @@ private:
eth::AssemblyItems m_constructorAssemblyItems;
QHash<LocationPair, QString> m_functions;
QHash<LocationPair, SolidityDeclaration> m_locals;
QHash<unsigned, SolidityDeclaration> m_storage;
QHash<unsigned, SolidityDeclarations> m_storage;
friend class CodeModel;
};

2
mix/MixClient.cpp

@ -185,7 +185,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
// execute on a state
if (!_call)
{
_state.execute(lastHashes, _t);
dev::eth::ExecutionResult er =_state.execute(lastHashes, _t);
if (_t.isCreation() && _state.code(d.contractAddress).empty())
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment"));
// collect watches

5
mix/QVariableDeclaration.h

@ -26,14 +26,15 @@
#pragma once
namespace dev
{
namespace solidity
{
class Type;
class VariableDeclaration;
}
namespace dev
{
namespace mix
{

6
mix/SolidityType.h

@ -25,6 +25,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include <QString>
#include <vector>
#include <libdevcore/Common.h>
namespace dev
{
@ -49,6 +50,7 @@ struct SolidityType
};
Type type;
unsigned size; //in bytes,
unsigned count;
bool array;
bool dynamicSize;
QString name;
@ -60,7 +62,11 @@ struct SolidityDeclaration
{
QString name;
SolidityType type;
dev::u256 slot;
unsigned offset;
};
using SolidityDeclarations = std::vector<SolidityDeclaration>;
}
}

Loading…
Cancel
Save