Skip to content

Commit

Permalink
- display outOfGas warning
Browse files Browse the repository at this point in the history
 - bugfix: display var located in memory
  • Loading branch information
yann300 committed Nov 25, 2015
1 parent 5f1c758 commit c6839c8
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 71 deletions.
3 changes: 3 additions & 0 deletions qml/BlockChain.qml
Original file line number Diff line number Diff line change
Expand Up @@ -572,13 +572,15 @@ ColumnLayout {
tr.logs = _r.logs
tr.isCall = false
tr.sender = _r.sender
tr.outOfGas = _r.outOfGas
tr.returnParameters = _r.returnParameters
var trModel = blockModel.getTransaction(blockIndex, trIndex)
trModel.returned = _r.returned
trModel.recordIndex = _r.recordIndex
trModel.logs = _r.logs
trModel.sender = _r.sender
trModel.returnParameters = _r.returnParameters
trModel.outOfGas = _r.outOfGas
blockModel.setTransaction(blockIndex, trIndex, trModel)
blockChainRepeater.select(blockIndex, trIndex, -1)
txExecuted(blockIndex, trIndex, -1)
Expand Down Expand Up @@ -628,6 +630,7 @@ ColumnLayout {
itemTr.recordIndex = _r.recordIndex
itemTr.logs = _r.logs
itemTr.returnParameters = _r.returnParameters
itemTr.outOfGas = _r.outOfGas
if (!itemTr.isContractCreation)
itemTr.parameters = _r.parameters
else if (transactionDialog.parameters)
Expand Down
7 changes: 5 additions & 2 deletions qml/Debugger.qml
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@ Rectangle {
anchors.fill: parent
tickmarksEnabled: true
stepSize: 1.0
onValueChanged: Debugger.jumpTo(value);
onValueChanged:
{
Debugger.jumpTo(value)
}

style: SliderStyle {
groove: Rectangle {
implicitHeight: 3
Expand Down Expand Up @@ -636,7 +640,6 @@ Rectangle {

function computeData()
{
console.log(JSON.stringify(_data))
model.clear()
for (var k in _data)
model.append({ "key": k, "value": JSON.stringify(_data[k]) })
Expand Down
11 changes: 10 additions & 1 deletion qml/Transaction.qml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,16 @@ ColumnLayout
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: ""
text: {
if (!tx.outOfGas)
return ""
else
{
color = "red"
font.italic = true
return "out of gas"
}
}
}
}

Expand Down
5 changes: 4 additions & 1 deletion qml/TransactionDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,10 @@ Dialog {
{
var gas = codeModel.txGas + codeModel.callStipend + parseInt(gasCost[0].gas)
estimatedGas.visible = true
estimatedGas.text = qsTr("Estimated cost: ") + gasCost[0].gas + " gas"
if (gasCost[0].isInfinite)
estimatedGas.text = qsTr("Estimated cost: ") + qsTr(" -- ")
else
estimatedGas.text = qsTr("Estimated cost: ") + gasCost[0].gas + " gas"
}
}

Expand Down
53 changes: 12 additions & 41 deletions src/ClientModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,12 +708,17 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t, QString
{
u256 pos = s.stack[l.first];
u256 offset = pos;
localValues[l.second->name()] = formatValue(l.second->type()->type(), s.memory, offset);
localValues[l.second->name()] = formatMemoryValue(l.second->type()->type(), s.memory, offset);
}
else if (loc == DataLocation::Storage)
localValues[l.second->name()] = formatStorageValue(l.second->type()->type(), s.storage, localDecl[l.second->name()].offset, localDecl[l.second->name()].slot);
else
localValues[l.second->name()] = formatValue(l.second->type()->type(), s.stack[l.first]);
{
ContractCallDataEncoder decoder;
u256 pos = 0;
bytes val = toBigEndian(s.stack[l.first]);
localValues[l.second->name()] = decoder.decodeType(l.second->type()->type(), val, pos);
}
}
locals["variables"] = localDeclarations;
locals["values"] = localValues;
Expand All @@ -738,44 +743,10 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t, QString
debugDataReady(debugData);
}

QVariant ClientModel::formatValue(SolidityType const& _type, u256 const& _value)
QVariant ClientModel::formatMemoryValue(SolidityType const& _type, bytes const& _value, u256& _offset)
{
bytes val = toBigEndian(_value);
u256 pos = 0;
return formatValue(_type, val, pos);
}

QVariant ClientModel::formatValue(SolidityType const& _type, bytes const& _value, u256& _offset)
{
QVariant res;
if (_type.array)
res = decoder.decodeRawArray(_type, _value, _offset);
else if (_type.members.size() > 0)
{
QVariantMap list;
for (unsigned k = 0; k < _type.members.size(); ++k)
{
auto m = _type.members.at(k);
if (m.type.array)
{
bytesConstRef value(_value.data() + static_cast<size_t>(_offset), 32);
bytes rawParam(32);
value.populate(&rawParam);
u256 arrayOffset = u256(decoder.decodeInt(rawParam));
list.insert(m.name, decoder.decodeRawArray(m.type, _value, arrayOffset));
_offset += 32;
}
else
list.insert(m.name, formatValue(m.type, _value, _offset));
}
return list;
}
else
{
res = decoder.decodeType(_type, _value, _offset);
_offset += 32;
}
return res;
ContractCallDataEncoder decoder;
return decoder.formatMemoryValue(_type, _value, _offset);
}

QVariant ClientModel::formatStorageValue(SolidityType const& _type, unordered_map<u256, u256> const& _storage, unsigned const& _offset, u256 const& _slot)
Expand Down Expand Up @@ -828,7 +799,7 @@ RecordLogEntry* ClientModel::lastBlock() const
strGas << blockInfo.gasUsed();
stringstream strNumber;
strNumber << blockInfo.number();
RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(dev::toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str()), QString(), tr("Block"), QVariantMap(), QVariantMap(), QVariantList(), RecordLogEntry::TxSource::MixGui);
RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(dev::toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str()), QString(), tr("Block"), QVariantMap(), QVariantMap(), QVariantList(), RecordLogEntry::TxSource::MixGui, false);
QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership);
return record;
}
Expand Down Expand Up @@ -1038,7 +1009,7 @@ void ClientModel::onNewTransaction(RecordLogEntry::TxSource _source)
label = address;

RecordLogEntry* log = new RecordLogEntry(recordIndex, transactionIndex, contract, function, value, address, returned, tr.isCall(), RecordLogEntry::RecordType::Transaction,
gasUsed, sender, label, inputParameters, returnParameters, logs, _source);
gasUsed, sender, label, inputParameters, returnParameters, logs, _source, tr.excepted == TransactionException::OutOfGasBase);
if (transactionIndex != QObject::tr("Call"))
m_lastTransactionIndex = transactionIndex;

Expand Down
10 changes: 6 additions & 4 deletions src/ClientModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class RecordLogEntry: public QObject
Q_PROPERTY(QVariantList logs MEMBER m_logs CONSTANT)
/// logs
Q_PROPERTY(TxSource source MEMBER m_source CONSTANT)
/// out of gas
Q_PROPERTY(bool outOfGas MEMBER m_outOfGas CONSTANT)

public:
enum RecordType
Expand All @@ -150,9 +152,9 @@ class RecordLogEntry: public QObject
RecordLogEntry():
m_recordIndex(0), m_call(false), m_type(RecordType::Transaction) {}
RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call, RecordType _type, QString _gasUsed,
QString _sender, QString _label, QVariantMap _inputParameters, QVariantMap _returnParameters, QVariantList _logs, TxSource _source):
QString _sender, QString _label, QVariantMap _inputParameters, QVariantMap _returnParameters, QVariantList _logs, TxSource _source, bool _outOfGas):
m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call), m_type(_type), m_gasUsed(_gasUsed),
m_sender(_sender), m_label(_label), m_inputParameters(_inputParameters), m_returnParameters(_returnParameters), m_logs(_logs), m_source(_source) {}
m_sender(_sender), m_label(_label), m_inputParameters(_inputParameters), m_returnParameters(_returnParameters), m_logs(_logs), m_source(_source), m_outOfGas(_outOfGas) {}

private:
unsigned m_recordIndex;
Expand All @@ -171,6 +173,7 @@ class RecordLogEntry: public QObject
QVariantMap m_returnParameters;
QVariantList m_logs;
TxSource m_source;
bool m_outOfGas;
};

/**
Expand Down Expand Up @@ -302,13 +305,12 @@ private slots:
void callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr);
void onNewTransaction(RecordLogEntry::TxSource _source);
void showDebuggerForTransaction(ExecutionResult const& _t, QString const& _label = "");
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
QVariant formatValue(SolidityType const& _type, dev::bytes const& _value, u256& _offset);
QString resolveToken(std::pair<QString, int> const& _value);
std::pair<QString, int> retrieveToken(QString const& _value);
std::pair<QString, int> resolvePair(QString const& _contractId);
QString serializeToken(std::pair<QString, int> const& _value) const;
QVariant formatStorageValue(SolidityType const& _type, std::unordered_map<dev::u256, dev::u256> const& _storage, unsigned const& _offset, dev::u256 const& _slot);
QVariant formatMemoryValue(SolidityType const& _type, bytes const& _value, u256& _offset);
void processNextTransactions();
void finalizeBlock();
void stopExecution();
Expand Down
76 changes: 54 additions & 22 deletions src/ContractCallDataEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,42 +255,57 @@ QString ContractCallDataEncoder::toChar(dev::bytes const& _b)
return str;
}

QJsonValue ContractCallDataEncoder::decodeArrayContent(SolidityType const& _type, bytes const& _value, u256& pos)
QJsonValue ContractCallDataEncoder::decodeArrayContent(SolidityType const& _type, bytes const& _value, u256& _pos)
{
if (_type.baseType->array)
{
QJsonArray sub = decodeArray(*_type.baseType, _value, pos);
QJsonArray sub;
if (_type.dataLocation == solidity::DataLocation::Memory)
{
//pointer to content always store here in case of Memory
bytesConstRef value(_value.data() + static_cast<size_t>(_pos), 32);
bytes rawParam(32);
value.populate(&rawParam);
u256 pos = u256(decodeInt(rawParam));
_pos += 32;
sub = decodeArray(*_type.baseType, _value, pos);
}
else
sub = decodeArray(*_type.baseType, _value, _pos);
return sub;
}
else
{
bytesConstRef value(_value.data() + static_cast<size_t>(pos), 32);
bytesConstRef value(_value.data() + static_cast<size_t>(_pos), 32);
bytes rawParam(32);
value.populate(&rawParam);
QVariant i = decode(*_type.baseType, rawParam);
_pos += 32;
return i.toString();
}
}

QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes const& _value, u256& pos)
QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes const& _value, u256& _pos)
{
QJsonArray array;
if (_value.size() < pos)
if (_value.size() < _pos)
return array;

bytesConstRef value(&_value);
u256 count = 0;
u256 offset = pos;
u256 valuePosition = pos;
u256 offset = _pos;
u256 valuePosition = _pos;

if (!_type.dynamicSize)
count = _type.count;
else
{
bytesConstRef value(_value.data() + static_cast<size_t>(pos), 32); // offset
bytesConstRef value(_value.data() + static_cast<size_t>(_pos), 32); // offset
bytes rawParam(32);
value.populate(&rawParam);
offset = u256(decodeInt(rawParam));
valuePosition = offset + 32;
pos += 32;
_pos += 32;
value = bytesConstRef(_value.data() + static_cast<size_t>(offset), 32); // count
value.populate(&rawParam);
count = u256(decodeInt(rawParam));
Expand All @@ -312,7 +327,7 @@ QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes
if (_type.dynamicSize)
array.append(decodeArrayContent(_type, _value, valuePosition));
else
array.append(decodeArrayContent(_type, _value, pos));
array.append(decodeArrayContent(_type, _value, _pos));
}
}
return array;
Expand Down Expand Up @@ -390,22 +405,39 @@ QVariant ContractCallDataEncoder::decodeRawArray(SolidityType const& _type, byte
return array.toVariantList();
}

QVariant ContractCallDataEncoder::formatStorageValue(SolidityType const& _type, unordered_map<u256, u256> const& _storage, unsigned _offset, u256 const& _slot, u256& _endSlot)
QVariant ContractCallDataEncoder::formatMemoryValue(SolidityType const& _type, bytes const& _value, u256& _offset)
{
dev::bytes b;
int k = 0;
for (auto const& sto: _storage)
ContractCallDataEncoder decoder;
QVariant res;
if (_type.array)
res = decoder.decodeRawArray(_type, _value, _offset);
else if (_type.members.size() > 0)
{
u256 slotValue = sto.second;
bytes slotBytes = toBigEndian(slotValue);
b += slotBytes;
stringstream s;
s << sto.first;
qDebug() << QString::fromStdString(s.str()) << " " << toString(slotBytes);
k++;
QVariantMap list;
for (unsigned k = 0; k < _type.members.size(); ++k)
{
auto m = _type.members.at(k);
if (m.type.array)
{
bytesConstRef value(_value.data() + static_cast<size_t>(_offset), 32);
bytes rawParam(32);
value.populate(&rawParam);
u256 arrayOffset = u256(decoder.decodeInt(rawParam));
list.insert(m.name, decoder.decodeRawArray(m.type, _value, arrayOffset));
_offset += 32;
}
else
list.insert(m.name, formatMemoryValue(m.type, _value, _offset));
}
return list;
}
qDebug() << " ==> " << toString(b);
else
res = decoder.decodeType(_type, _value, _offset);
return res;
}

QVariant ContractCallDataEncoder::formatStorageValue(SolidityType const& _type, unordered_map<u256, u256> const& _storage, unsigned _offset, u256 const& _slot, u256& _endSlot)
{
_endSlot = _slot;
if (_type.array)
return formatStorageArray(_type, _storage, _offset, _slot, _endSlot);
Expand Down
2 changes: 2 additions & 0 deletions src/ContractCallDataEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class ContractCallDataEncoder
QVariant decodeRawArray(SolidityType const& _type, bytes const& _value, u256& pos);
/// Decode struct stored in storage
QVariant formatStorageStruct(SolidityType const& _type, std::unordered_map<u256, u256> const& _storage, u256 _slot, u256& _endSlot);
/// Decode value stored in memory
QVariant formatMemoryValue(SolidityType const& _type, bytes const& _value, u256& _offset);

private:
unsigned encodeSingleItem(QString const& _data, SolidityType const& _type, bytes& _dest);
Expand Down

0 comments on commit c6839c8

Please sign in to comment.