Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
dd91f190c4
  1. 2
      evmjit
  2. 15
      libdevcore/CommonJS.cpp
  3. 8
      libdevcore/CommonJS.h
  4. 2
      libethereum/BlockChain.cpp
  5. 4
      libethereum/BlockChain.h
  6. 3
      libethereum/Executive.cpp
  7. 3
      libethereum/Executive.h
  8. 24
      mix/AppContext.cpp
  9. 30
      mix/AppContext.h
  10. 171
      mix/AssemblyDebuggerControl.cpp
  11. 84
      mix/AssemblyDebuggerControl.h
  12. 103
      mix/AssemblyDebuggerCtrl.cpp
  13. 70
      mix/AssemblyDebuggerCtrl.h
  14. 67
      mix/AssemblyDebuggerModel.cpp
  15. 14
      mix/AssemblyDebuggerModel.h
  16. 30
      mix/CodeEditorExtensionManager.cpp
  17. 17
      mix/CodeEditorExtensionManager.h
  18. 30
      mix/ConstantCompilationControl.cpp
  19. 15
      mix/ConstantCompilationControl.h
  20. 3
      mix/ConstantCompilationModel.cpp
  21. 10
      mix/ConstantCompilationModel.h
  22. 131
      mix/ContractCallDataEncoder.cpp
  23. 64
      mix/ContractCallDataEncoder.h
  24. 19
      mix/DebuggingStateWrapper.cpp
  25. 74
      mix/DebuggingStateWrapper.h
  26. 5
      mix/Extension.cpp
  27. 11
      mix/Extension.h
  28. 9
      mix/KeyEventManager.h
  29. 1
      mix/MixApplication.h
  30. 30
      mix/QBasicNodeDefinition.h
  31. 48
      mix/QContractDefinition.cpp
  32. 53
      mix/QContractDefinition.h
  33. 37
      mix/QFunctionDefinition.cpp
  34. 58
      mix/QFunctionDefinition.h
  35. 49
      mix/QVariableDeclaration.h
  36. 55
      mix/QVariableDefinition.cpp
  37. 72
      mix/QVariableDefinition.h
  38. 40
      mix/TransactionBuilder.cpp
  39. 221
      mix/TransactionListModel.cpp
  40. 168
      mix/TransactionListModel.h
  41. 56
      mix/TransactionListView.cpp
  42. 54
      mix/TransactionListView.h
  43. 2
      mix/qml.qrc
  44. 5
      mix/qml/AlertMessageDialog.qml
  45. 8
      mix/qml/BasicContent.qml
  46. 1
      mix/qml/BasicMessage.qml
  47. 70
      mix/qml/Debugger.qml
  48. 105
      mix/qml/MainContent.qml
  49. 7
      mix/qml/ModalDialog.qml
  50. 219
      mix/qml/TransactionDialog.qml
  51. 89
      mix/qml/TransactionList.qml
  52. 10
      mix/qml/js/Debugger.js
  53. 6
      mix/qml/main.qml
  54. 4
      test/stSystemOperationsTestFiller.json
  55. 65
      test/trie.cpp
  56. 2392
      test/vmArithmeticTestFiller.json

2
evmjit

@ -1 +1 @@
Subproject commit 66d5a2b5cdf1361dcf0205b191dd12be090ed224
Subproject commit 3df5a125fa0baa579528abce80402118cad803fd

15
libdevcore/CommonJS.cpp

@ -42,8 +42,6 @@ bytes padded(bytes _b, unsigned _l)
{
while (_b.size() < _l)
_b.insert(_b.begin(), 0);
while (_b.size() < _l)
_b.push_back(0);
return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l)));
}
@ -54,15 +52,23 @@ bytes unpadded(bytes _b)
return _b;
}
std::string unpadLeft(std::string _b)
{
auto p = _b.find_first_not_of('0');
if (p == std::string::npos)
return "0";
return _b.substr(p, _b.length() - 1);
}
std::string prettyU256(u256 _n)
{
unsigned inc = 0;
std::string raw;
std::ostringstream s;
if (!(_n >> 64))
s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")";
s << " " << (uint64_t)_n << " (0x" << std::hex << (uint64_t)_n << ")";
else if (!~(_n >> 64))
s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")";
s << " " << (int64_t)_n << " (0x" << std::hex << (int64_t)_n << ")";
else if ((_n >> 160) == 0)
{
Address a = right160(_n);
@ -113,5 +119,4 @@ Address fromString(std::string const& _sn)
return Address();
}
}

8
libdevcore/CommonJS.h

@ -46,11 +46,19 @@ inline std::string toJS(dev::bytes const& _n)
return "0x" + dev::toHex(_n);
}
/// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex.
bytes jsToBytes(std::string const& _s);
/// Add '0' on the head of _b until _l.
bytes padded(bytes _b, unsigned _l);
/// Removing all trailing '0'. Returns empty array if input contains only '0' char.
bytes unpadded(bytes _s);
/// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'.
std::string unpadLeft(std::string _s);
/// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256.
std::string prettyU256(u256 _n);
/// Convert h256 into user-readable string (by directly using std::string constructor).
std::string fromRaw(h256 _n, unsigned* _inc = nullptr);
/// Convert string to Address (h160), returns empty address if (_a.size != 40).
Address fromString(std::string const& _a);
template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s)

2
libethereum/BlockChain.cpp

@ -71,7 +71,7 @@ std::map<Address, Account> const& dev::eth::genesisState()
return s_ret;
}
BlockInfo* BlockChain::s_genesis = nullptr;
std::unique_ptr<BlockInfo> BlockChain::s_genesis;
boost::shared_mutex BlockChain::x_genesis;
ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)

4
libethereum/BlockChain.h

@ -132,7 +132,7 @@ public:
h256Set allUnclesFrom(h256 _parent) const;
/// @returns the genesis block header.
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); (s_genesis = new BlockInfo)->populate(&gb); } return *s_genesis; }
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new BlockInfo); s_genesis->populate(&gb); } return *s_genesis; }
/// @returns the genesis block as its RLP-encoded byte array.
/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
@ -211,7 +211,7 @@ private:
/// Static genesis info and its lock.
static boost::shared_mutex x_genesis;
static BlockInfo* s_genesis;
static std::unique_ptr<BlockInfo> s_genesis;
};
std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);

3
libethereum/Executive.cpp

@ -1,16 +1,13 @@
/*
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/>.
*/

3
libethereum/Executive.h

@ -1,16 +1,13 @@
/*
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/>.
*/

24
mix/AppContext.cpp

@ -26,12 +26,15 @@
#include <QMessageBox>
#include <QQmlComponent>
#include <QQmlApplicationEngine>
#include "libdevcrypto/FileSystem.h"
#include <libwebthree/WebThree.h>
#include <libdevcrypto/FileSystem.h>
#include <libsolidity/CompilerStack.h>
#include "KeyEventManager.h"
#include "AppContext.h"
using namespace dev;
using namespace dev::mix;
using namespace dev::eth;
using namespace dev::solidity;
using namespace dev::mix;
AppContext* AppContext::Instance = nullptr;
@ -40,6 +43,7 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_applicationEngine = std::unique_ptr<QQmlApplicationEngine>(_engine);
m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager());
m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"}));
m_compiler = std::unique_ptr<CompilerStack>(new CompilerStack()); //TODO : to move in a codel model structure.
}
QQmlApplicationEngine* AppContext::appEngine()
@ -47,11 +51,6 @@ QQmlApplicationEngine* AppContext::appEngine()
return m_applicationEngine.get();
}
dev::eth::Client* AppContext::getEthereumClient()
{
return m_webThree->ethereum();
}
void AppContext::initKeyEventManager(QObject* _res)
{
QObject* mainContent = _res->findChild<QObject*>("mainContent", Qt::FindChildrenRecursively);
@ -66,6 +65,11 @@ KeyEventManager* AppContext::getKeyEventManager()
return m_keyEventManager.get();
}
CompilerStack* AppContext::compiler()
{
return m_compiler.get();
}
void AppContext::setApplicationContext(QQmlApplicationEngine* _engine)
{
if (Instance == nullptr)
@ -74,9 +78,9 @@ void AppContext::setApplicationContext(QQmlApplicationEngine* _engine)
void AppContext::displayMessageDialog(QString _title, QString _message)
{
QObject* dialogWin = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = m_applicationEngine.get()->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close");
// TODO : move to a UI dedicated layer.
QObject* dialogWin = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively);
dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml"));
dialogWin->setProperty("title", _title);
dialogWin->setProperty("width", "250");

30
mix/AppContext.h

@ -27,28 +27,48 @@
#pragma once
#include <memory>
#include <QQmlApplicationEngine>
#include "libwebthree/WebThree.h"
#include <libsolidity/CompilerStack.h>
#include <libwebthree/WebThree.h>
#include "KeyEventManager.h"
namespace dev
{
class WebThreeDirect;
namespace solidity
{
class CompilerStack;
}
}
namespace dev
{
namespace mix
{
/**
* @brief Provides access to application scope variable.
*/
class AppContext: public QObject
{
Q_OBJECT
public:
AppContext(QQmlApplicationEngine* _engine);
~AppContext() {}
/// Get the current QQmlApplicationEngine instance.
static AppContext* getInstance() { return Instance; }
/// Renew QQMLApplicationEngine with a new instance.
static void setApplicationContext(QQmlApplicationEngine* _engine);
/// Get the current QQMLApplicationEngine instance.
QQmlApplicationEngine* appEngine();
dev::eth::Client* getEthereumClient();
/// Initialize KeyEventManager (used to handle key pressed event).
void initKeyEventManager(QObject* _obj);
/// Get the current KeyEventManager instance.
KeyEventManager* getKeyEventManager();
/// Get the current Compiler instance (used to parse and compile contract code).
dev::solidity::CompilerStack* compiler();
/// Display an alert message.
void displayMessageDialog(QString _title, QString _message);
private:
@ -56,12 +76,14 @@ private:
std::unique_ptr<QQmlApplicationEngine> m_applicationEngine;
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<KeyEventManager> m_keyEventManager;
std::unique_ptr<solidity::CompilerStack> m_compiler;
public slots:
/// Delete the current instance when application quit.
void quitApplication() { delete Instance; }
/// Initialize components after the loading of the main QML view.
void resourceLoaded(QObject* _obj, QUrl _url) { Q_UNUSED(_url); initKeyEventManager(_obj); }
};
}
}

171
mix/AssemblyDebuggerControl.cpp

@ -0,0 +1,171 @@
/*
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 AssemblyDebuggerControl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* display opcode debugging.
*/
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QVariableDefinition.h>
#include <QQmlContext>
#include <QModelIndex>
#include <libdevcore/CommonJS.h>
#include <libethereum/Transaction.h>
#include "AssemblyDebuggerModel.h"
#include "AssemblyDebuggerControl.h"
#include "KeyEventManager.h"
#include "AppContext.h"
#include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
#include "QContractDefinition.h"
#include "QVariableDeclaration.h"
#include "ContractCallDataEncoder.h"
using namespace dev::eth;
using namespace dev::mix;
AssemblyDebuggerControl::AssemblyDebuggerControl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog)
{
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*");
qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>");
qRegisterMetaType<QList<QVariableDeclaration*>>("QList<QVariableDeclaration*>");
qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*");
qRegisterMetaType<AssemblyDebuggerData>("AssemblyDebuggerData");
qRegisterMetaType<DebuggingStatusResult>("DebuggingStatusResult");
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QVariableDefinition*>, QList<QObject*>, AssemblyDebuggerData)),
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QVariableDefinition*>, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection);
m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel);
m_compilation = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel);
m_doc = _doc;
}
QString AssemblyDebuggerControl::contentUrl() const
{
return QStringLiteral("qrc:/qml/Debugger.qml");
}
QString AssemblyDebuggerControl::title() const
{
return QApplication::tr("debugger");
}
void AssemblyDebuggerControl::start() const
{
//start to listen on F5
m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int)));
}
void AssemblyDebuggerControl::keyPressed(int _key)
{
if (_key == Qt::Key_F5)
{
QtConcurrent::run([this]()
{
deployContract(m_doc->toPlainText());
});
}
else if (_key == Qt::Key_F6)
{
m_modelDebugger->resetState();
AppContext::getInstance()->displayMessageDialog(QApplication::tr("State status"), QApplication::tr("State reseted ... need to redeploy contract"));
}
}
void AssemblyDebuggerControl::callContract(TransactionSettings _tr, dev::Address _contract)
{
CompilerResult compilerRes = m_compilation->compile(m_doc->toPlainText());
if (!compilerRes.success)
AppContext::getInstance()->displayMessageDialog("debugger","compilation failed");
else
{
ContractCallDataEncoder c;
std::shared_ptr<QContractDefinition> contractDef = QContractDefinition::Contract(m_doc->toPlainText());
QFunctionDefinition* f = nullptr;
for (int k = 0; k < contractDef->functions().size(); k++)
{
if (contractDef->functions().at(k)->name() == _tr.functionId)
{
f = (QFunctionDefinition*)contractDef->functions().at(k);
break;
}
}
if (!f)
AppContext::getInstance()->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("function not found. Please redeploy this contract."));
else
{
c.encode(f->index());
for (int k = 0; k < f->parameters().size(); k++)
{
QVariableDeclaration* var = (QVariableDeclaration*)f->parameters().at(k);
c.encode(var, _tr.parameterValues[var->name()]);
}
DebuggingContent debuggingContent = m_modelDebugger->callContract(_contract, c.encodedData(), _tr);
debuggingContent.returnParameters = c.decode(f->returnParameters(), debuggingContent.returnValue);
finalizeExecution(debuggingContent);
}
}
}
void AssemblyDebuggerControl::deployContract(QString _source)
{
CompilerResult compilerRes = m_compilation->compile(_source);
if (!compilerRes.success)
emit dataAvailable(false, DebuggingStatusResult::Compilationfailed);
else
{
m_previousDebugResult = m_modelDebugger->deployContract(compilerRes.bytes);
finalizeExecution(m_previousDebugResult);
}
}
void AssemblyDebuggerControl::finalizeExecution(DebuggingContent _debuggingContent)
{
//we need to wrap states in a QObject before sending to QML.
QList<QObject*> wStates;
for(int i = 0; i < _debuggingContent.machineStates.size(); i++)
{
QPointer<DebuggingStateWrapper> s(new DebuggingStateWrapper(_debuggingContent.executionCode, _debuggingContent.executionData.toBytes()));
s->setState(_debuggingContent.machineStates.at(i));
wStates.append(s);
}
AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(_debuggingContent.executionCode);
emit dataAvailable(true, DebuggingStatusResult::Ok, _debuggingContent.returnParameters, wStates, code);
}
void AssemblyDebuggerControl::updateGUI(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParam, QList<QObject*> const& _wStates, AssemblyDebuggerData const& _code)
{
Q_UNUSED(_reason);
if (_success)
{
m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates));
m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code)));
m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code)));
m_appEngine->rootContext()->setContextProperty("contractCallReturnParameters", QVariant::fromValue(new QVariableDefinitionList(_returnParam)));
this->addContentOn(this);
}
else
m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed"));
}
void AssemblyDebuggerControl::runTransaction(TransactionSettings const& _tr)
{
QtConcurrent::run([this, _tr]()
{
callContract(_tr, m_previousDebugResult.contractAddress);
});
}

84
mix/AssemblyDebuggerControl.h

@ -0,0 +1,84 @@
/*
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 AssemblyDebuggerControl.h
* @author Yann yann@ethdev.com
* @date 2014
* Extension which display debugging steps in assembly code.
*/
#pragma once
#include <QKeySequence>
#include <QTextDocument>
#include "Extension.h"
#include "ConstantCompilationModel.h"
#include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h"
#include "AppContext.h"
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;
enum DebuggingStatusResult
{
Ok,
Compilationfailed
};
Q_DECLARE_METATYPE(AssemblyDebuggerData)
Q_DECLARE_METATYPE(DebuggingStatusResult)
Q_DECLARE_METATYPE(dev::mix::DebuggingContent)
namespace dev
{
namespace mix
{
/**
* @brief Extension which display transaction creation or transaction call debugging. handle: F5 to deploy contract, F6 to reset state.
*/
class AssemblyDebuggerControl: public Extension
{
Q_OBJECT
public:
AssemblyDebuggerControl(QTextDocument* _doc);
~AssemblyDebuggerControl() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
private:
void deployContract(QString _source);
void callContract(TransactionSettings _tr, Address _contract);
void finalizeExecution(DebuggingContent _content);
std::unique_ptr<AssemblyDebuggerModel> m_modelDebugger;
std::unique_ptr<ConstantCompilationModel> m_compilation;
DebuggingContent m_previousDebugResult; //TODO: to be replaced in a more consistent struct. Used for now to keep the contract address in case of future transaction call.
QTextDocument* m_doc;
public slots:
/// Handle key pressed. F5 deploy contract - F6 reset state.
void keyPressed(int);
/// Update UI with machine states result. Display a modal dialog.
void updateGUI(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParams = QList<QVariableDefinition*>(), QList<QObject*> const& _wStates = QList<QObject*>(), AssemblyDebuggerData const& _code = AssemblyDebuggerData());
/// Run the given transaction.
void runTransaction(TransactionSettings const& _tr);
signals:
/// Emited when machine states are available.
void dataAvailable(bool _success, DebuggingStatusResult const& _reason, QList<QVariableDefinition*> const& _returnParams = QList<QVariableDefinition*>(), QList<QObject*> const& _wStates = QList<QObject*>(), AssemblyDebuggerData const& _code = AssemblyDebuggerData());
};
}
}

103
mix/AssemblyDebuggerCtrl.cpp

@ -1,103 +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 AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* display opcode debugging.
*/
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QQmlContext>
#include <QModelIndex>
#include "libethereum/Transaction.h"
#include "AssemblyDebuggerModel.h"
#include "AssemblyDebuggerCtrl.h"
#include "TransactionBuilder.h"
#include "KeyEventManager.h"
#include "AppContext.h"
#include "DebuggingStateWrapper.h"
using namespace dev::mix;
AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::ModalDialog)
{
qRegisterMetaType<AssemblyDebuggerData>();
qRegisterMetaType<DebuggingStatusResult>();
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)),
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection);
m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel);
m_doc = _doc;
}
QString AssemblyDebuggerCtrl::contentUrl() const
{
return QStringLiteral("qrc:/qml/Debugger.qml");
}
QString AssemblyDebuggerCtrl::title() const
{
return QApplication::tr("debugger");
}
void AssemblyDebuggerCtrl::start() const
{
//start to listen on F5
m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int)));
}
void AssemblyDebuggerCtrl::keyPressed(int _key)
{
if (_key == Qt::Key_F5)
{
QString code = m_doc->toPlainText();
QtConcurrent::run([this, code]()
{
if (!m_modelDebugger->compile(m_doc->toPlainText()))
{
emit dataAvailable(false, DebuggingStatusResult::Compilationfailed);
return;
}
u256 gasPrice = 10000000000000;
u256 gas = 1000000;
u256 amount = 100;
DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(amount, gasPrice, gas, m_doc->toPlainText());
//we need to wrap states in a QObject before sending to QML.
QList<QObject*> wStates;
for(int i = 0; i < debuggingContent.states.size(); i++)
{
DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes(), this);
s->setState(debuggingContent.states.at(i));
wStates.append(s);
}
AssemblyDebuggerData code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this);
emit dataAvailable(true, DebuggingStatusResult::Ok, wStates, code);
});
}
}
void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates, AssemblyDebuggerData _code)
{
Q_UNUSED(reason);
if (success)
{
m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates));
m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code)));
m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code)));
this->addContentOn(this);
}
else
m_ctx->displayMessageDialog(QApplication::tr("debugger"), QApplication::tr("compilation failed"));
}

70
mix/AssemblyDebuggerCtrl.h

@ -1,70 +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 AssemblyDebuggerCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QKeySequence>
#include "QTextDocument"
#include "Extension.h"
#include "ConstantCompilationModel.h"
#include "AssemblyDebuggerModel.h"
#include "AppContext.h"
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;
enum DebuggingStatusResult
{
Ok,
Compilationfailed
};
Q_DECLARE_METATYPE(AssemblyDebuggerData)
Q_DECLARE_METATYPE(DebuggingStatusResult)
namespace dev
{
namespace mix
{
class AssemblyDebuggerCtrl: public Extension
{
Q_OBJECT
public:
AssemblyDebuggerCtrl(QTextDocument*);
~AssemblyDebuggerCtrl() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
private:
std::unique_ptr<AssemblyDebuggerModel> m_modelDebugger;
QTextDocument* m_doc;
public slots:
void keyPressed(int);
void updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
signals:
void dataAvailable(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
};
}
}

67
mix/AssemblyDebuggerModel.cpp

@ -11,7 +11,7 @@
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 AssemblyDebuggerModel.h
/** @file AssemblyDebuggerModel.cpp
* @author Yann yann@ethdev.com
* @date 2014
* used as a model to debug contract assembly code.
@ -24,7 +24,7 @@
#include <libethereum/Transaction.h>
#include <libethereum/ExtVM.h>
#include "AppContext.h"
#include "TransactionBuilder.h"
#include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h"
#include "ConstantCompilationModel.h"
#include "DebuggingStateWrapper.h"
@ -38,15 +38,14 @@ AssemblyDebuggerModel::AssemblyDebuggerModel():
m_baseState(Address(), m_overlayDB, BaseState::Empty)
{
m_baseState.addBalance(m_userAccount.address(), 10000000 * ether);
m_executiveState = m_baseState;
m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState, LastHashes(), 0));
}
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction)
DebuggingContent AssemblyDebuggerModel::executeTransaction(bytesConstRef const& _rawTransaction)
{
// Reset the state back to our clean premine.
m_executiveState = m_baseState;
QList<DebuggingState> states;
QList<DebuggingState> machineStates;
m_currentExecution.reset(new Executive(m_executiveState, LastHashes(), 0));
m_currentExecution->setup(_rawTransaction);
std::vector<DebuggingState const*> levels;
bytes code;
@ -65,21 +64,21 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by
}
if (levels.size() < ext.depth)
levels.push_back(&states.back());
levels.push_back(&machineStates.back());
else
levels.resize(ext.depth);
states.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(),
machineStates.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(),
vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
m_currentExecution->go(onOp);
cdebug << states.size();
m_currentExecution->finalize(onOp);
m_executiveState.completeMine();
DebuggingContent d;
d.states = states;
d.returnValue = m_currentExecution->out().toVector();
d.machineStates = machineStates;
d.executionCode = code;
d.executionData = data;
d.contentAvailable = true;
@ -87,34 +86,32 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::by
return d;
}
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(
dev::u256 _value,
dev::u256 _gasPrice,
dev::u256 _gas,
QString _code
)
DebuggingContent AssemblyDebuggerModel::deployContract(bytes const& _code)
{
ConstantCompilationModel compiler;
CompilerResult res = compiler.compile(_code);
if (!res.success)
{
DebuggingContent r;
r.contentAvailable = false;
r.message = QApplication::tr("compilation failed");
return r;
}
u256 gasPrice = 10000000000000;
u256 gas = 1000000;
u256 amount = 100;
Transaction _tr(amount, gasPrice, min(gas, m_baseState.gasLimitRemaining()), _code, m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret());
bytes b = _tr.rlp();
dev::bytesConstRef bytesRef = &b;
DebuggingContent d = executeTransaction(bytesRef);
h256 th = sha3(rlpList(_tr.sender(), _tr.nonce()));
d.contractAddress = right160(th);
return d;
}
TransactionBuilder trBuild;
Transaction tr = trBuild.getCreationTransaction(_value, _gasPrice, min(_gas, m_baseState.gasLimitRemaining()), res.bytes,
m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret());
DebuggingContent AssemblyDebuggerModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr)
{
Transaction tr = Transaction(_tr.value, _tr.gasPrice, min(_tr.gas, m_baseState.gasLimitRemaining()), _contract, _data, m_executiveState.transactionsFrom(dev::toAddress(m_userAccount.secret())), m_userAccount.secret());
bytes b = tr.rlp();
dev::bytesConstRef bytesRef = &b;
return getContractInitiationDebugStates(bytesRef);
DebuggingContent d = executeTransaction(bytesRef);
d.contractAddress = tr.receiveAddress();
return d;
}
bool AssemblyDebuggerModel::compile(QString _code)
void AssemblyDebuggerModel::resetState()
{
ConstantCompilationModel compiler;
CompilerResult res = compiler.compile(_code);
return res.success;
// Reset the state back to our clean premine.
m_executiveState = m_baseState;
}

14
mix/AssemblyDebuggerModel.h

@ -14,7 +14,7 @@
/** @file AssemblyDebuggerModel.h
* @author Yann yann@ethdev.com
* @date 2014
* serves as a model to debug contract assembly code.
* Used as a model to debug contract assembly code.
*/
#pragma once
@ -26,6 +26,7 @@
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
namespace dev
{
@ -39,9 +40,12 @@ class AssemblyDebuggerModel
{
public:
AssemblyDebuggerModel();
DebuggingContent getContractInitiationDebugStates(u256, u256, u256, QString);
DebuggingContent getContractInitiationDebugStates(bytesConstRef);
bool compile(QString);
/// Call function in a already deployed contract.
DebuggingContent callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr);
/// Deploy the contract described by _code.
DebuggingContent deployContract(bytes const& _code);
/// Reset state to the base state.
void resetState();
private:
KeyPair m_userAccount;
@ -49,8 +53,8 @@ private:
eth::State m_baseState;
eth::State m_executiveState;
std::unique_ptr<eth::Executive> m_currentExecution;
DebuggingContent executeTransaction(dev::bytesConstRef const& _rawTransaction);
};
}
}

30
mix/CodeEditorExtensionManager.cpp

@ -26,8 +26,9 @@
#include <QQmlComponent>
#include <QQuickTextDocument>
#include <libevm/VM.h>
#include "ConstantCompilationCtrl.h"
#include "AssemblyDebuggerCtrl.h"
#include "ConstantCompilationControl.h"
#include "AssemblyDebuggerControl.h"
#include "TransactionListView.h"
#include "AppContext.h"
#include "CodeEditorExtensionManager.h"
using namespace dev::mix;
@ -48,7 +49,17 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
{
QQuickTextDocument* qqdoc = doc.value<QQuickTextDocument*>();
if (qqdoc)
{
m_doc = qqdoc->textDocument();
auto args = QApplication::arguments();
if (args.length() > 1)
{
QString path = args[1];
QFile file(path);
if (file.exists() && file.open(QFile::ReadOnly))
m_doc->setPlainText(file.readAll());
}
}
}
}
catch (...)
@ -59,8 +70,12 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions()
{
initExtension(std::make_shared<ConstantCompilationCtrl>(m_doc));
initExtension(std::make_shared<AssemblyDebuggerCtrl>(m_doc));
initExtension(std::make_shared<ConstantCompilationControl>(m_doc));
std::shared_ptr<AssemblyDebuggerControl> debug = std::make_shared<AssemblyDebuggerControl>(m_doc);
std::shared_ptr<TransactionListView> tr = std::make_shared<TransactionListView>(m_doc);
QObject::connect(tr->model(), &TransactionListModel::transactionStarted, debug.get(), &AssemblyDebuggerControl::runTransaction);
initExtension(debug);
initExtension(tr);
}
void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
@ -71,6 +86,8 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab)
_ext->addTabOn(m_tabView);
else if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightTab)
_ext->addTabOn(m_rightTabView);
}
catch (...)
{
@ -88,6 +105,11 @@ void CodeEditorExtensionManager::setEditor(QQuickItem* _editor)
this->initExtensions();
}
void CodeEditorExtensionManager::setRightTabView(QQuickItem* _tabView)
{
m_rightTabView = _tabView;
}
void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView)
{
m_tabView = _tabView;

17
mix/CodeEditorExtensionManager.h

@ -22,40 +22,49 @@
#pragma once
#include "memory"
#include <QQuickItem>
#include <QTextDocument>
#include <QVector>
#include "ConstantCompilationCtrl.h"
#include "ConstantCompilationControl.h"
namespace dev
{
namespace mix
{
/**
* @brief Init and provides connection between extensions.
*/
class CodeEditorExtensionManager: public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickItem* editor MEMBER m_editor WRITE setEditor)
Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView)
Q_PROPERTY(QQuickItem* rightTabView MEMBER m_rightTabView WRITE setRightTabView)
public:
CodeEditorExtensionManager() {}
~CodeEditorExtensionManager();
/// Initialize all extensions.
void initExtensions();
/// Initialize extension.
void initExtension(std::shared_ptr<Extension>);
/// Set current text editor.
void setEditor(QQuickItem*);
/// Set current tab view
void setTabView(QQuickItem*);
/// Set current right tab view.
void setRightTabView(QQuickItem*);
private:
QQuickItem* m_editor;
QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView;
QQuickItem* m_rightTabView;
QTextDocument* m_doc;
void loadEditor(QQuickItem*);
void loadEditor(QQuickItem* _editor);
};
}
}

30
mix/ConstantCompilationCtrl.cpp → mix/ConstantCompilationControl.cpp

@ -14,56 +14,58 @@
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 ConstantCompilationCtrl.cpp
/** @file ConstantCompilationControl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQmlContext>
#include <QQuickItem>
#include <QtCore/QFileInfo>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtCore/QtCore>
#include <QDebug>
#include "ConstantCompilationCtrl.h"
#include "ConstantCompilationControl.h"
#include "ConstantCompilationModel.h"
#include "QContractDefinition.h"
using namespace dev::mix;
ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab)
ConstantCompilationControl::ConstantCompilationControl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab)
{
m_editor = _doc;
m_compilationModel = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel());
}
QString ConstantCompilationCtrl::contentUrl() const
QString ConstantCompilationControl::contentUrl() const
{
return QStringLiteral("qrc:/qml/BasicContent.qml");
}
QString ConstantCompilationCtrl::title() const
QString ConstantCompilationControl::title() const
{
return QApplication::tr("compiler");
}
void ConstantCompilationCtrl::start() const
void ConstantCompilationControl::start() const
{
connect(m_editor, SIGNAL(contentsChange(int,int,int)), this, SLOT(compile()));
}
void ConstantCompilationCtrl::compile()
void ConstantCompilationControl::compile()
{
QString codeContent = m_editor->toPlainText().replace("\n", "");
if (codeContent.isEmpty())
{
resetOutPut();
return;
else
{
CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " "));
writeOutPut(res);
}
CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " "));
writeOutPut(res);
}
void ConstantCompilationCtrl::resetOutPut()
void ConstantCompilationControl::resetOutPut()
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
@ -71,7 +73,7 @@ void ConstantCompilationCtrl::resetOutPut()
content->setProperty("text", "");
}
void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res)
void ConstantCompilationControl::writeOutPut(CompilerResult const& _res)
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
@ -80,13 +82,11 @@ void ConstantCompilationCtrl::writeOutPut(CompilerResult const& _res)
status->setProperty("text", "succeeded");
status->setProperty("color", "green");
content->setProperty("text", _res.hexCode);
qDebug() << QString(QApplication::tr("compile succeeded") + " " + _res.hexCode);
}
else
{
status->setProperty("text", "failure");
status->setProperty("color", "red");
content->setProperty("text", _res.comment);
qDebug() << QString(QApplication::tr("compile failed") + " " + _res.comment);
}
}

15
mix/ConstantCompilationCtrl.h → mix/ConstantCompilationControl.h

@ -11,7 +11,7 @@
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 ConstantCompilationCtrl.h
/** @file ConstantCompilationControl.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
@ -28,13 +28,16 @@ namespace dev
namespace mix
{
class ConstantCompilationCtrl: public Extension
/**
* @brief Extension which display assembly code of the contract being edited.
*/
class ConstantCompilationControl: public Extension
{
Q_OBJECT
public:
ConstantCompilationCtrl(QTextDocument*);
~ConstantCompilationCtrl() {}
ConstantCompilationControl(QTextDocument* _doc);
~ConstantCompilationControl() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
@ -42,13 +45,13 @@ public:
private:
QTextDocument* m_editor;
std::unique_ptr<ConstantCompilationModel> m_compilationModel;
void writeOutPut(CompilerResult const&);
void writeOutPut(CompilerResult const& _res);
void resetOutPut();
public slots:
/// Compile text editor content.
void compile();
};
}
}

3
mix/ConstantCompilationModel.cpp

@ -24,13 +24,16 @@
#include <QObject>
#include <libevm/VM.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libsolidity/NameAndTypeResolver.h>
#include "ConstantCompilationModel.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace dev::mix;
using namespace dev::solidity;
CompilerResult ConstantCompilationModel::compile(QString _code)
{

10
mix/ConstantCompilationModel.h

@ -22,14 +22,18 @@
#pragma once
#include <libevm/VM.h>
#include <QObject>
#include <libevm/VM.h>
#include <libsolidity/AST.h>
namespace dev
{
namespace mix
{
/**
* @brief Provides compiler result information.
*/
struct CompilerResult
{
QString hexCode;
@ -38,12 +42,16 @@ struct CompilerResult
bool success;
};
/**
* @brief Compile source code using the solidity library.
*/
class ConstantCompilationModel
{
public:
ConstantCompilationModel() {}
~ConstantCompilationModel() {}
/// Compile code.
CompilerResult compile(QString _code);
};

131
mix/ContractCallDataEncoder.cpp

@ -0,0 +1,131 @@
/*
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 ContractCallDataEncoder.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QDebug>
#include <QMap>
#include <QStringList>
#include <libdevcore/CommonJS.h>
#include <libsolidity/AST.h>
#include "QVariableDeclaration.h"
#include "QVariableDefinition.h"
#include "ContractCallDataEncoder.h"
using namespace dev;
using namespace dev::solidity;
using namespace dev::mix;
bytes ContractCallDataEncoder::encodedData()
{
return m_encodedData;
}
void ContractCallDataEncoder::encode(int _functionIndex)
{
bytes i = jsToBytes(std::to_string(_functionIndex));
m_encodedData.insert(m_encodedData.end(), i.begin(), i.end());
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, bool _value)
{
return encode(_dec, QString(formatBool(_value)));
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, QString _value)
{
int padding = this->padding(_dec->type());
bytes data = padded(jsToBytes(_value.toStdString()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
}
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, u256 _value)
{
int padding = this->padding(_dec->type());
std::ostringstream s;
s << std::hex << "0x" << _value;
bytes data = padded(jsToBytes(s.str()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
encodedData();
}
QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> _returnParameters, bytes _value)
{
QList<QVariableDefinition*> r;
std::string returnValue = toJS(_value);
returnValue = returnValue.substr(2, returnValue.length() - 1);
for (int k = 0; k <_returnParameters.length(); k++)
{
QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k);
int padding = this->padding(dec->type());
std::string rawParam = returnValue.substr(0, padding * 2);
r.append(new QVariableDefinition(dec, convertToReadable(unpadLeft(rawParam), dec)));
returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1);
}
return r;
}
int ContractCallDataEncoder::padding(QString type)
{
// TODO : to be improved (load types automatically from solidity library).
if (type.indexOf("uint") != -1)
return integerPadding(type.remove("uint").toInt());
else if (type.indexOf("int") != -1)
return integerPadding(type.remove("int").toInt());
else if (type.indexOf("bool") != -1)
return 1;
else if ((type.indexOf("address") != -1))
return 20;
else
return 0;
}
int ContractCallDataEncoder::integerPadding(int bitValue)
{
return bitValue / 8;
}
QString ContractCallDataEncoder::formatBool(bool _value)
{
return (_value ? "1" : "0");
}
QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec)
{
if (_dec->type().indexOf("int") != -1)
return convertToInt(_v);
else if (_dec->type().indexOf("bool") != -1)
return convertToBool(_v);
else
return QString::fromStdString(_v);
}
QString ContractCallDataEncoder::convertToBool(std::string _v)
{
return _v == "1" ? "true" : "false";
}
QString ContractCallDataEncoder::convertToInt(std::string _v)
{
//TO DO to be improve to manage all int, uint size (128, 256, ...) in ethereum QML types task #612.
int x = std::stol(_v, nullptr, 16);
std::stringstream ss;
ss << std::dec << x;
return QString::fromStdString(ss.str());
}

64
mix/ContractCallDataEncoder.h

@ -0,0 +1,64 @@
/*
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 ContractCallDataEncoder.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include "QVariableDeclaration.h"
#include "QVariableDefinition.h"
namespace dev
{
namespace mix
{
/**
* @brief Encode/Decode data to be sent to a transaction or to be displayed in a view.
*/
class ContractCallDataEncoder
{
public:
ContractCallDataEncoder() {}
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, QString _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, u256 _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration* _dec, bool _value);
/// Encode index of the function to call.
void encode(int _functionIndex);
/// Decode variable in order to be sent to QML view.
QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> _dec, bytes _value);
/// Get all encoded data encoded by encode function.
bytes encodedData();
private:
int padding(QString _type);
bytes m_encodedData;
static QString convertToReadable(std::string _v, QVariableDeclaration* _dec);
static QString convertToBool(std::string _v);
static QString convertToInt(std::string _v);
static int integerPadding(int _bitValue);
static QString formatBool(bool _value);
};
}
}

19
mix/DebuggingStateWrapper.cpp

@ -22,17 +22,18 @@
#include <QApplication>
#include <QDebug>
#include "libevmcore/Instruction.h"
#include "libdevcore/CommonJS.h"
#include "libdevcrypto/Common.h"
#include "libevmcore/Instruction.h"
#include "libdevcore/Common.h"
#include <QPointer>
#include <libevmcore/Instruction.h>
#include <libdevcore/CommonJS.h>
#include <libdevcrypto/Common.h>
#include <libevmcore/Instruction.h>
#include <libdevcore/Common.h>
#include "DebuggingStateWrapper.h"
using namespace dev;
using namespace dev::eth;
using namespace dev::mix;
std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code, QObject* _objUsedAsParent)
std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCode(const bytes& _code)
{
QList<QObject*> codeStr;
QMap<int, int> codeMapping;
@ -52,7 +53,7 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc)));
i += bc;
}
HumanReadableCode* humanCode = new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line, _objUsedAsParent);
QPointer<HumanReadableCode> humanCode(new HumanReadableCode(QString::fromStdString(out.str()) + " " + s, line));
codeStr.append(humanCode);
}
catch (...)
@ -62,7 +63,7 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
break; // probably hit data segment
}
}
return std::make_tuple(codeStr, new QQMLMap(codeMapping, _objUsedAsParent));
return std::make_tuple(codeStr, QPointer<QQMLMap>(new QQMLMap(codeMapping)));
}
QString DebuggingStateWrapper::gasLeft()
@ -99,7 +100,7 @@ QString DebuggingStateWrapper::debugStorage()
{
std::stringstream s;
for (auto const& i: m_state.storage)
s << "@" << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << prettyU256(i.second);
s << "@" << prettyU256(i.first) << " " << prettyU256(i.second);
return QString::fromStdString(s.str());
}

74
mix/DebuggingStateWrapper.h

@ -23,15 +23,20 @@
#pragma once
#include <QStringList>
#include "libethereum/State.h"
#include "libethereum/Executive.h"
#include "libdevcore/Common.h"
#include <QMap>
#include <libdevcore/Common.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include "QVariableDefinition.h"
namespace dev
{
namespace mix
{
/**
* @brief Store information about a machine state.
*/
struct DebuggingState
{
uint64_t steps;
@ -47,13 +52,19 @@ struct DebuggingState
std::vector<DebuggingState const*> levels;
};
/**
* @brief Store information about a machine states.
*/
struct DebuggingContent
{
QList<DebuggingState> states;
QList<DebuggingState> machineStates;
bytes executionCode;
bytesConstRef executionData;
Address contractAddress;
bool contentAvailable;
QString message;
bytes returnValue;
QList<QVariableDefinition*> returnParameters;
};
/**
@ -62,12 +73,14 @@ struct DebuggingContent
class HumanReadableCode: public QObject
{
Q_OBJECT
Q_PROPERTY(QString line READ line)
Q_PROPERTY(int processIndex READ processIndex)
Q_PROPERTY(QString line READ line CONSTANT)
Q_PROPERTY(int processIndex READ processIndex CONSTANT)
public:
HumanReadableCode(QString _line, int _processIndex, QObject* _parent): QObject(_parent), m_line(_line), m_processIndex(_processIndex) {}
HumanReadableCode(QString _line, int _processIndex): QObject(), m_line(_line), m_processIndex(_processIndex) {}
/// Get the assembly code line.
QString line() { return m_line; }
/// Get corresponding index.
int processIndex() { return m_processIndex; }
private:
@ -84,7 +97,8 @@ class QQMLMap: public QObject
Q_OBJECT
public:
QQMLMap(QMap<int, int> _map, QObject* _parent): QObject(_parent), m_map(_map) { }
QQMLMap(QMap<int, int> _map): QObject(), m_map(_map) { }
/// Get the value associated with _key store in n_map.
Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); }
private:
@ -97,36 +111,51 @@ private:
class DebuggingStateWrapper: public QObject
{
Q_OBJECT
Q_PROPERTY(int step READ step)
Q_PROPERTY(int curPC READ curPC)
Q_PROPERTY(QString gasCost READ gasCost)
Q_PROPERTY(QString gas READ gas)
Q_PROPERTY(QString gasLeft READ gasLeft)
Q_PROPERTY(QString debugStack READ debugStack)
Q_PROPERTY(QString debugStorage READ debugStorage)
Q_PROPERTY(QString debugMemory READ debugMemory)
Q_PROPERTY(QString debugCallData READ debugCallData)
Q_PROPERTY(QString headerInfo READ headerInfo)
Q_PROPERTY(QString endOfDebug READ endOfDebug)
Q_PROPERTY(QStringList levels READ levels)
Q_PROPERTY(int step READ step CONSTANT)
Q_PROPERTY(int curPC READ curPC CONSTANT)
Q_PROPERTY(QString gasCost READ gasCost CONSTANT)
Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasLeft READ gasLeft CONSTANT)
Q_PROPERTY(QString debugStack READ debugStack CONSTANT)
Q_PROPERTY(QString debugStorage READ debugStorage CONSTANT)
Q_PROPERTY(QString debugMemory READ debugMemory CONSTANT)
Q_PROPERTY(QString debugCallData READ debugCallData CONSTANT)
Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT)
Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT)
Q_PROPERTY(QStringList levels READ levels CONSTANT)
public:
DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {}
DebuggingStateWrapper(bytes _code, bytes _data): QObject(), m_code(_code), m_data(_data) {}
/// Get the step of this machine states.
int step() { return (int)m_state.steps; }
/// Get the proccessed code index.
int curPC() { return (int)m_state.curPC; }
/// Get gas left.
QString gasLeft();
/// Get gas cost.
QString gasCost();
/// Get gas used.
QString gas();
/// Get stack.
QString debugStack();
/// Get storage.
QString debugStorage();
/// Get memory.
QString debugMemory();
/// Get call data.
QString debugCallData();
/// Get info to be displayed in the header.
QString headerInfo();
/// get end of debug information.
QString endOfDebug();
/// Get all previous steps.
QStringList levels();
/// Get the current processed machine state.
DebuggingState state() { return m_state; }
/// Set the current processed machine state.
void setState(DebuggingState _state) { m_state = _state; }
static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& _code, QObject* _objUsedAsParent);
/// Convert all machine state in human readable code.
static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& _code);
private:
DebuggingState m_state;
@ -135,5 +164,4 @@ private:
};
}
}

5
mix/Extension.cpp

@ -20,6 +20,7 @@
#include <QMessageBox>
#include <QDebug>
#include <libevm/VM.h>
#include <libwebthree/WebThree.h>
#include "Extension.h"
#include "AppContext.h"
using namespace dev;
@ -65,10 +66,10 @@ void Extension::addContentOn(QObject* _view)
Q_UNUSED(_view);
if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog)
{
QQmlComponent* component = new QQmlComponent(AppContext::getInstance()->appEngine(), QUrl(contentUrl()), _view);
QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("modalDialogContent", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close");
dialogWinComponent->setProperty("source", contentUrl());
dialogWinComponent->setProperty("sourceComponent", QVariant::fromValue(component));
dialogWin->setProperty("title", title());
QMetaObject::invokeMethod(dialogWin, "open");
}

11
mix/Extension.h

@ -31,6 +31,7 @@ namespace mix
enum ExtensionDisplayBehavior
{
Tab,
RightTab,
ModalDialog
};
@ -42,12 +43,19 @@ class Extension: public QObject
public:
Extension();
Extension(ExtensionDisplayBehavior _displayBehavior);
/// Return the QML url of the view to display.
virtual QString contentUrl() const { return ""; }
/// Return the title of this extension.
virtual QString title() const { return ""; }
/// Initialize extension.
virtual void start() const {}
void addContentOn(QObject* _tabView);
/// Add the view define in contentUrl() in the _view QObject.
void addContentOn(QObject* _view);
/// Add the view define in contentUrl() in the _view QObject (_view has to be a tab).
void addTabOn(QObject* _view);
/// Modify the display behavior of this extension.
void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; }
/// Get the display behavior of thi extension.
ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; }
protected:
@ -61,5 +69,4 @@ private:
};
}
}

9
mix/KeyEventManager.h

@ -17,12 +17,13 @@
/** @file KeyEventManager.h
* @author Yann yann@ethdev.com
* @date 2014
* use as an event handler for all classes which need keyboard interactions
* Used as an event handler for all classes which need keyboard interactions
*/
#pragma once
#include <QObject>
#include <QVariant>
class KeyEventManager: public QObject
{
@ -30,13 +31,17 @@ class KeyEventManager: public QObject
public:
KeyEventManager() {}
/// Allows _receiver to handle key pressed event.
void registerEvent(const QObject* _receiver, const char* _slot);
/// Unregister _receiver.
void unRegisterEvent(QObject* _receiver);
signals:
void onKeyPressed(int);
/// Emited when a key is pressed.
void onKeyPressed(int _event);
public slots:
/// Called when a key is pressed.
void keyPressed(QVariant _event);
};

1
mix/MixApplication.h

@ -41,5 +41,4 @@ public:
};
}
}

30
mix/TransactionBuilder.h → mix/QBasicNodeDefinition.h

@ -1,43 +1,49 @@
/*
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 TransactionBuilder.h
/** @file QBasicNodeDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QString>
#include "libdevcore/Common.h"
#include "libethereum/Transaction.h"
#include <QObject>
#include <libsolidity/AST.h>
namespace dev
{
namespace mix
{
class TransactionBuilder
class QBasicNodeDefinition: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
public:
TransactionBuilder() {}
dev::eth::Transaction getBasicTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas,
QString address, bytes _data, dev::u256 _nonce, Secret _secret) const;
dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas,
dev::bytes _data, dev::u256 _nonce, Secret _secret) const;
QBasicNodeDefinition(): QObject() {}
~QBasicNodeDefinition() {}
QBasicNodeDefinition(solidity::Declaration const* _d): QObject(), m_name(QString::fromStdString(_d->getName())) {}
/// Get the name of the node.
QString name() const { return m_name; }
private:
QString m_name;
};
}
}

48
mix/QContractDefinition.cpp

@ -0,0 +1,48 @@
/*
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 QContractDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <QObject>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/NameAndTypeResolver.h>
#include "AppContext.h"
#include "QContractDefinition.h"
using namespace dev::solidity;
using namespace dev::mix;
std::shared_ptr<QContractDefinition> QContractDefinition::Contract(QString _source)
{
CompilerStack* comp = AppContext::getInstance()->compiler();
comp->addSource("contract", _source.toStdString());
comp->parse();
ContractDefinition const* def = &comp->getContractDefinition(comp->getContractNames().front());
return std::make_shared<QContractDefinition>(def);
}
void QContractDefinition::initQFunctions()
{
std::vector<FunctionDefinition const*> functions = m_contract->getInterfaceFunctions();
for (unsigned i = 0; i < functions.size(); i++)
m_functions.append(new QFunctionDefinition(functions.at(i), i));
}

53
mix/QContractDefinition.h

@ -0,0 +1,53 @@
/*
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 QContractDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#pragma once
#include <QObject>
#include <libsolidity/AST.h>
#include "QFunctionDefinition.h"
#include "QBasicNodeDefinition.h"
namespace dev
{
namespace mix
{
class QContractDefinition: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QList<QFunctionDefinition*> functions READ functions)
public:
QContractDefinition(solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_contract), m_contract(_contract) { initQFunctions(); }
/// Get all the functions of the contract.
QList<QFunctionDefinition*> functions() const { return m_functions; }
/// Get the description (functions, parameters, return parameters, ...) of the contract describes by _code.
static std::shared_ptr<QContractDefinition> Contract(QString _code);
private:
solidity::ContractDefinition const* m_contract;
QList<QFunctionDefinition*> m_functions;
void initQFunctions();
};
}
}

37
mix/QFunctionDefinition.cpp

@ -0,0 +1,37 @@
/*
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 QFunctionDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libsolidity/AST.h>
#include "QVariableDeclaration.h"
#include "QFunctionDefinition.h"
using namespace dev::solidity;
using namespace dev::mix;
void QFunctionDefinition::initQParameters()
{
std::vector<std::shared_ptr<VariableDeclaration>> parameters = m_functions->getParameterList().getParameters();
for (unsigned i = 0; i < parameters.size(); i++)
m_parameters.append(new QVariableDeclaration(parameters.at(i).get()));
std::vector<std::shared_ptr<VariableDeclaration>> returnParameters = m_functions->getReturnParameters();
for (unsigned i = 0; i < returnParameters.size(); i++)
m_returnParameters.append(new QVariableDeclaration(returnParameters.at(i).get()));
}

58
mix/QFunctionDefinition.h

@ -0,0 +1,58 @@
/*
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 QFunctionDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#pragma once
#include <QObject>
#include <libsolidity/AST.h>
#include <QVariableDeclaration.h>
#include "QBasicNodeDefinition.h"
namespace dev
{
namespace mix
{
class QFunctionDefinition: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QList<QVariableDeclaration*> parameters READ parameters)
Q_PROPERTY(int index READ index)
public:
QFunctionDefinition(solidity::FunctionDefinition const* _f, int _index): QBasicNodeDefinition(_f), m_index(_index), m_functions(_f) { initQParameters(); }
/// Get all input parameters of this function.
QList<QVariableDeclaration*> parameters() const { return m_parameters; }
/// Get all return parameters of this function.
QList<QVariableDeclaration*> returnParameters() const { return m_returnParameters; }
/// Get the index of this function on the contract ABI.
int index() const { return m_index; }
private:
int m_index;
solidity::FunctionDefinition const* m_functions;
QList<QVariableDeclaration*> m_parameters;
QList<QVariableDeclaration*> m_returnParameters;
void initQParameters();
};
}
}

49
mix/QVariableDeclaration.h

@ -0,0 +1,49 @@
/*
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.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libsolidity/AST.h>
#include "QBasicNodeDefinition.h"
#pragma once
namespace dev
{
namespace mix
{
class QVariableDeclaration: public QBasicNodeDefinition
{
Q_OBJECT
Q_PROPERTY(QString type READ type CONSTANT)
public:
QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_variable(_v) {}
/// Get the type of this variable.
QString type() const { return QString::fromStdString(m_variable->getType()->toString()); }
private:
solidity::VariableDeclaration const* m_variable;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*)

55
mix/QVariableDefinition.cpp

@ -0,0 +1,55 @@
/*
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 "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);
}

72
mix/QVariableDefinition.h

@ -0,0 +1,72 @@
/*
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
*/
#pragma once
#include <QAbstractListModel>
#include "QVariableDeclaration.h"
namespace dev
{
namespace mix
{
class QVariableDefinition: public QObject
{
Q_OBJECT
Q_PROPERTY(QString value READ value CONSTANT)
Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT)
public:
QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {}
/// Return the associated declaration of this variable definition.
QVariableDeclaration* declaration() const { return m_dec; }
/// Return the variable value.
QString value() const { return m_value; }
private:
QString m_value;
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;
};
}
}
Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*)

40
mix/TransactionBuilder.cpp

@ -1,40 +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 TransactionBuilder.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include "libethereum/Executive.h"
#include "libdevcore/CommonJS.h"
#include "libdevcore/Common.h"
#include "AppContext.h"
#include "TransactionBuilder.h"
using namespace dev::mix;
using namespace dev::eth;
using namespace dev;
Transaction TransactionBuilder::getCreationTransaction(u256 _value, u256 _gasPrice, u256 _gas,
bytes _data, u256 _nonce, Secret _secret) const
{
return Transaction(_value, _gasPrice, _gas, _data, _nonce, _secret);
}
Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice, u256 _gas,
QString _address, bytes _data, u256 _nonce, Secret _secret) const
{
return Transaction(_value, _gasPrice, _gas, dev::fromString(_address.toStdString()), _data, _nonce, _secret);
}

221
mix/TransactionListModel.cpp

@ -0,0 +1,221 @@
/*
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 TransactionListModel.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QObject>
#include <QQmlEngine>
#include <QTextDocument>
#include <QAbstractListModel>
#include <libdevcore/CommonJS.h>
#include "TransactionListModel.h"
#include "QContractDefinition.h"
#include "QFunctionDefinition.h"
#include "QVariableDeclaration.h"
namespace dev
{
namespace mix
{
/// @todo Move this to QML
u256 fromQString(QString const& _s)
{
return dev::jsToU256(_s.toStdString());
}
/// @todo Move this to QML
QString toQString(u256 _value)
{
std::ostringstream s;
s << _value;
return QString::fromStdString(s.str());
}
TransactionListItem::TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent):
QObject(_parent), m_index(_index), m_title(_t.title), m_functionId(_t.functionId), m_value(toQString(_t.value)),
m_gas(toQString(_t.gas)), m_gasPrice(toQString(_t.gasPrice))
{}
TransactionListModel::TransactionListModel(QObject* _parent, QTextDocument* _document):
QAbstractListModel(_parent), m_document(_document)
{
qRegisterMetaType<TransactionListItem*>("TransactionListItem*");
}
QHash<int, QByteArray> TransactionListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[TitleRole] = "title";
roles[IdRole] = "transactionIndex";
return roles;
}
int TransactionListModel::rowCount(QModelIndex const& _parent) const
{
Q_UNUSED(_parent);
return m_transactions.size();
}
QVariant TransactionListModel::data(QModelIndex const& _index, int _role) const
{
if (_index.row() < 0 || _index.row() >= (int)m_transactions.size())
return QVariant();
auto const& transaction = m_transactions.at(_index.row());
switch (_role)
{
case TitleRole:
return QVariant(transaction.title);
case IdRole:
return QVariant(_index.row());
default:
return QVariant();
}
}
///@todo: get parameters from code model
QList<TransactionParameterItem*> buildParameters(QTextDocument* _document, TransactionSettings const& _transaction, QString const& _functionId)
{
QList<TransactionParameterItem*> params;
try
{
std::shared_ptr<QContractDefinition> contract = QContractDefinition::Contract(_document->toPlainText());
auto functions = contract->functions();
for (auto f : functions)
{
if (f->name() != _functionId)
continue;
auto parameters = f->parameters();
//build a list of parameters for a function. If the function is selected as current, add parameter values as well
for (auto p : parameters)
{
QString paramValue;
if (f->name() == _transaction.functionId)
{
auto paramValueIter = _transaction.parameterValues.find(p->name());
if (paramValueIter != _transaction.parameterValues.cend())
paramValue = toQString(paramValueIter->second);
}
TransactionParameterItem* item = new TransactionParameterItem(p->name(), p->type(), paramValue);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
params.append(item);
}
}
}
catch (boost::exception const&)
{
//TODO:
}
return params;
}
///@todo: get fnctions from code model
QList<QString> TransactionListModel::getFunctions()
{
QList<QString> functionNames;
try
{
QString code = m_document->toPlainText();
std::shared_ptr<QContractDefinition> contract(QContractDefinition::Contract(code));
auto functions = contract->functions();
for (auto f : functions)
{
functionNames.append(f->name());
}
}
catch (boost::exception const&)
{
}
return functionNames;
}
QVariantList TransactionListModel::getParameters(int _index, QString const& _functionId)
{
TransactionSettings const& transaction = (_index >= 0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
auto plist = buildParameters(m_document, transaction, _functionId);
QVariantList vl;
for (QObject* p : plist)
vl.append(QVariant::fromValue(p));
return vl;
}
TransactionListItem* TransactionListModel::getItem(int _index)
{
TransactionSettings const& transaction = (_index >= 0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
TransactionListItem* item = new TransactionListItem(_index, transaction, nullptr);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
return item;
}
void TransactionListModel::edit(QObject* _data)
{
//these properties come from TransactionDialog QML object
///@todo change the model to a qml component
int index = _data->property("transactionIndex").toInt();
QString title = _data->property("transactionTitle").toString();
QString gas = _data->property("gas").toString();
QString gasPrice = _data->property("gasPrice").toString();
QString value = _data->property("transactionValue").toString();
QString functionId = _data->property("functionId").toString();
QAbstractListModel* paramsModel = qvariant_cast<QAbstractListModel*>(_data->property("transactionParams"));
TransactionSettings transaction(title, functionId, fromQString(value), fromQString(gas), fromQString(gasPrice));
int paramCount = paramsModel->rowCount(QModelIndex());
for (int p = 0; p < paramCount; ++p)
{
QString paramName = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole).toString();
QString paramValue = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole + 2).toString();
if (!paramValue.isEmpty() && !paramName.isEmpty())
transaction.parameterValues[paramName] = fromQString(paramValue);
}
if (index >= 0 && index < (int)m_transactions.size())
{
beginRemoveRows(QModelIndex(), index, index);
m_transactions.erase(m_transactions.begin() + index);
endRemoveRows();
}
else
index = rowCount(QModelIndex());
beginInsertRows(QModelIndex(), index, index);
m_transactions.push_back(transaction);
emit countChanged();
endInsertRows();
}
int TransactionListModel::getCount() const
{
return rowCount(QModelIndex());
}
void TransactionListModel::runTransaction(int _index)
{
TransactionSettings tr = m_transactions.at(_index);
emit transactionStarted(tr);
}
}
}

168
mix/TransactionListModel.h

@ -0,0 +1,168 @@
/*
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 TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QObject>
#include <QVariant>
#include <QAbstractListModel>
#include <QHash>
#include <QByteArray>
#include <libdevcore/Common.h>
#include <libethcore/CommonEth.h>
class QTextDocument;
namespace dev
{
namespace mix
{
/// Backend transaction config class
struct TransactionSettings
{
TransactionSettings():
value(0), gas(10000), gasPrice(10 * dev::eth::szabo) {}
TransactionSettings(QString const& _title, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice):
title(_title), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {}
/// User specified transaction title
QString title;
/// Contract function name
QString functionId;
/// Transaction value
u256 value;
/// Gas
u256 gas;
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
std::map<QString, u256> parameterValues;
};
/// QML transaction parameter class
class TransactionParameterItem: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString type READ type CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionParameterItem(QString const& _name, QString const& _type, QString const& _value):
m_name(_name), m_type(_type), m_value(_value) {}
/// Parameter name, set by contract definition
QString name() { return m_name; }
/// Parameter type, set by contract definition
QString type() { return m_type; }
/// Parameter value, set by user
QString value() { return m_value; }
private:
QString m_name;
QString m_type;
QString m_value;
};
class TransactionListItem: public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index CONSTANT)
Q_PROPERTY(QString title READ title CONSTANT)
Q_PROPERTY(QString functionId READ functionId CONSTANT)
Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasPrice READ gasPrice CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent);
/// User specified transaction title
QString title() { return m_title; }
/// Gas
QString gas() { return m_gas; }
/// Gas cost
QString gasPrice() { return m_gasPrice; }
/// Transaction value
QString value() { return m_value; }
/// Contract function name
QString functionId() { return m_functionId; }
/// Index of this transaction in the transactions list
int index() { return m_index; }
private:
int m_index;
QString m_title;
QString m_functionId;
QString m_value;
QString m_gas;
QString m_gasPrice;
};
/// QML model for a list of transactions
class TransactionListModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ getCount() NOTIFY countChanged())
enum Roles
{
TitleRole = Qt::DisplayRole,
IdRole = Qt::UserRole + 1
};
public:
TransactionListModel(QObject* _parent, QTextDocument* _document);
~TransactionListModel() {}
QHash<int, QByteArray> roleNames() const override;
int rowCount(QModelIndex const& _parent) const override;
QVariant data(QModelIndex const& _index, int _role) const override;
int getCount() const;
/// Apply changes from transaction dialog. Argument is a dialog model as defined in TransactionDialog.qml
/// @todo Change that to transaction item
Q_INVOKABLE void edit(QObject* _data);
/// @returns transaction item for a give index
Q_INVOKABLE TransactionListItem* getItem(int _index);
/// @returns a list of functions for current contract
Q_INVOKABLE QList<QString> getFunctions();
/// @returns function parameters along with parameter values if set. @see TransactionParameterItem
Q_INVOKABLE QVariantList getParameters(int _id, QString const& _functionId);
/// Launch transaction execution UI handler
Q_INVOKABLE void runTransaction(int _index);
signals:
/// Transaction count has changed
void countChanged();
/// Transaction has been launched
void transactionStarted(dev::mix::TransactionSettings);
private:
std::vector<TransactionSettings> m_transactions;
QTextDocument* m_document;
};
}
}

56
mix/TransactionListView.cpp

@ -0,0 +1,56 @@
/*
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 TransactionListView.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQuickItem>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include "TransactionListView.h"
#include "TransactionListModel.h"
using namespace dev::mix;
TransactionListView::TransactionListView(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::RightTab)
{
m_editor = _doc;
m_model.reset(new TransactionListModel(this, _doc));
m_appEngine->rootContext()->setContextProperty("transactionListModel", m_model.get());
}
TransactionListView::~TransactionListView()
{
//implementation is in cpp file so that all types deleted are complete
}
QString TransactionListView::contentUrl() const
{
return QStringLiteral("qrc:/qml/TransactionList.qml");
}
QString TransactionListView::title() const
{
return QApplication::tr("Transactions");
}
void TransactionListView::start() const
{
}

54
mix/TransactionListView.h

@ -0,0 +1,54 @@
/*
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 TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QTextDocument>
#include "Extension.h"
namespace dev
{
namespace mix
{
class TransactionListModel;
/// Transactions list control
/// @todo This should be moved into state as a sequence
class TransactionListView: public Extension
{
Q_OBJECT
public:
TransactionListView(QTextDocument*);
~TransactionListView();
void start() const override;
QString title() const override;
QString contentUrl() const override;
/// @returns the underlying model
TransactionListModel* model() const { return m_model.get(); }
private:
QTextDocument* m_editor;
std::unique_ptr<TransactionListModel> m_model;
};
}
}

2
mix/qml.qrc

@ -7,6 +7,8 @@
<file>qml/Debugger.qml</file>
<file>qml/js/Debugger.js</file>
<file>qml/BasicMessage.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/TransactionList.qml</file>
<file>qml/ModalDialog.qml</file>
<file>qml/AlertMessageDialog.qml</file>
</qresource>

5
mix/qml/AlertMessageDialog.qml

@ -22,6 +22,9 @@ Window
}
function close()
{
visible = false
visible = false;
alertMessageDialogContent.source = "";
alertMessageDialogContent.sourceComponent = undefined;
alertMessageDialog.destroy();
}
}

8
mix/qml/BasicContent.qml

@ -7,13 +7,13 @@ Rectangle {
height: parent.height
color: "lightgray"
Text {
font.pointSize: 7
font.pointSize: 9
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 3
anchors.leftMargin: 3
height: 9
font.family: "Sego UI light"
font.family: "Monospace"
objectName: "status"
id: status
}
@ -23,8 +23,8 @@ Rectangle {
anchors.leftMargin: 10
anchors.top: status.bottom
anchors.topMargin: 3
font.pointSize: 7
font.family: "Sego UI light"
font.pointSize: 9
font.family: "Monospace"
height: parent.height * 0.8
width: parent.width - 20
wrapMode: Text.Wrap

1
mix/qml/BasicMessage.qml

@ -16,6 +16,7 @@ Rectangle {
objectName: "messageContent"
id: messageTxt
text: ""
wrapMode: "Wrap"
}
}

70
mix/qml/Debugger.qml

@ -8,18 +8,54 @@ import "js/Debugger.js" as Debugger
Rectangle {
anchors.fill: parent;
color: "lightgrey"
Component.onCompleted: Debugger.init();
Rectangle {
color: "transparent"
id: headerInfo
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: 30
height: 60
anchors.top: parent.top
Label {
anchors.centerIn: parent
font.family: "Verdana"
font.pointSize: 9
font.italic: true
id: headerInfoLabel
Column {
width: parent.width
height: parent.height
Rectangle {
color: "transparent"
width: parent.width
height: 30
Label {
anchors.centerIn: parent
font.family: "Verdana"
font.pointSize: 9
font.italic: true
id: headerInfoLabel
}
}
Rectangle {
color: "transparent"
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
height: 30
ListView {
orientation: ListView.Horizontal
anchors.centerIn: parent;
width: parent.width
id: headerReturnList
delegate: renderDelegateReturnValues
}
Component {
id: renderDelegateReturnValues
Item {
id: wrapperItem
width: 80
Text {
anchors.centerIn: parent
text: variable.declaration.name + " = " + variable.value
font.pointSize: 9
}
}
}
}
}
}
@ -37,7 +73,7 @@ Rectangle {
anchors.topMargin: 10
anchors.top: headerInfo.bottom
anchors.left: parent.left
height: parent.height - 30
height: parent.height - 70
width: parent.width * 0.5
ListView {
@ -46,7 +82,6 @@ Rectangle {
width: 200
anchors.horizontalCenter: parent.horizontalCenter
id: statesList
Component.onCompleted: Debugger.init();
model: humanReadableExecutionCode
delegate: renderDelegate
highlight: highlightBar
@ -94,7 +129,7 @@ Rectangle {
font.letterSpacing: 2
width: parent.width
height: 15
text: "callstack"
text: qsTr("callstack")
}
ListView {
@ -140,7 +175,7 @@ Rectangle {
width: parent.width
height: 15
anchors.top : parent.top
text: "debug stack"
text: qsTr("debug stack")
}
TextArea {
anchors.bottom: parent.bottom
@ -148,7 +183,7 @@ Rectangle {
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id:debugStackTxt
id: debugStackTxt
readOnly: true;
}
}
@ -166,7 +201,7 @@ Rectangle {
width: parent.width
height: 15
anchors.top : parent.top
text: "debug memory"
text: qsTr("debug memory")
}
TextArea {
anchors.bottom: parent.bottom
@ -192,7 +227,7 @@ Rectangle {
width: parent.width
height: 15
anchors.top : parent.top
text: "debug storage"
text: qsTr("debug storage")
}
TextArea {
anchors.bottom: parent.bottom
@ -200,7 +235,7 @@ Rectangle {
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id:debugStorageTxt
id: debugStorageTxt
readOnly: true;
}
}
@ -218,12 +253,15 @@ Rectangle {
width: parent.width
height: 15
anchors.top : parent.top
text: "debug calldata"
text: qsTr("debug calldata")
}
TextArea {
anchors.bottom: parent.bottom
width: parent.width
height: parent.height - 15
font.family: "Verdana"
font.pointSize: 8
font.letterSpacing: 2
id: debugCallDataTxt
readOnly: true;
}

105
mix/qml/MainContent.qml

@ -16,47 +16,66 @@ Rectangle {
anchors.fill: parent
height: parent.height
width: parent.width;
id:root
SplitView {
anchors.fill: parent
orientation: Qt.Vertical
Rectangle {
anchors.top: parent.top
id: contentView
width: parent.width
height: parent.height * 0.7
TextArea {
id: codeEditor
height: parent.height
font.family: "Verdana"
font.pointSize: 9
width: parent.width
anchors.centerIn: parent
tabChangesFocus: false
Keys.onPressed: {
if (event.key === Qt.Key_Tab) {
codeEditor.insert(codeEditor.cursorPosition, "\t");
event.accepted = true;
}
}
}
}
Rectangle {
anchors.bottom: parent.bottom
id: contextualView
width: parent.width
Layout.minimumHeight: 20
height: parent.height * 0.3
TabView {
id: contextualTabs
antialiasing: true
anchors.fill: parent
style: TabStyle {}
}
}
CodeEditorExtensionManager {
tabView: contextualTabs
editor: codeEditor
}
}
id:root
SplitView {
orientation: Qt.Horizontal
anchors.fill: parent
SplitView {
//anchors.fill: parent
width: parent.width * 0.8
orientation: Qt.Vertical
Rectangle {
anchors.top: parent.top
id: contentView
width: parent.width
height: parent.height * 0.7
TextArea {
id: codeEditor
height: parent.height
font.family: "Monospace"
font.pointSize: 12
width: parent.width
anchors.centerIn: parent
tabChangesFocus: false
Keys.onPressed: {
if (event.key === Qt.Key_Tab) {
codeEditor.insert(codeEditor.cursorPosition, "\t");
event.accepted = true;
}
}
}
}
Rectangle {
anchors.bottom: parent.bottom
id: contextualView
width: parent.width
Layout.minimumHeight: 20
height: parent.height * 0.3
TabView {
id: contextualTabs
antialiasing: true
anchors.fill: parent
style: TabStyle {}
}
}
}
Rectangle {
anchors.right: parent.right
id: rightPaneView
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 20
TabView {
id: rightPaneTabs
antialiasing: true
anchors.fill: parent
//style: TabStyle {}
}
}
CodeEditorExtensionManager {
tabView: contextualTabs
rightTabView: rightPaneTabs
editor: codeEditor
}
}
}

7
mix/qml/ModalDialog.qml

@ -18,10 +18,13 @@ Window
}
function open()
{
visible = true
visible = true;
}
function close()
{
visible = false
visible = false;
modalDialogContent.source = "";
modalDialogContent.sourceComponent = undefined;
modalDialog.destroy();
}
}

219
mix/qml/TransactionDialog.qml

@ -0,0 +1,219 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
Window {
modality: Qt.WindowModal
width:640
height:480
visible: false
function open()
{
visible = true;
}
function close()
{
visible = false;
}
property alias focus : titleField.focus
property alias transactionTitle : titleField.text
property int transactionIndex
property alias transactionParams : paramsModel;
property alias gas : gasField.text;
property alias gasPrice : gasPriceField.text;
property alias transactionValue : valueField.text;
property alias functionId : functionComboBox.currentText;
property var model;
signal accepted;
function reset(index, m) {
model = m;
var item = model.getItem(index);
transactionIndex = index;
transactionTitle = item.title;
gas = item.gas;
gasPrice = item.gasPrice;
transactionValue = item.value;
var functionId = item.functionId;
functionsModel.clear();
var functionIndex = -1;
var functions = model.getFunctions();
for (var f = 0; f < functions.length; f++) {
functionsModel.append({ text: functions[f] });
if (functions[f] === item.functionId)
functionIndex = f;
}
functionComboBox.currentIndex = functionIndex;
}
function loadParameters() {
if (!paramsModel)
return;
paramsModel.clear();
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var parameters = model.getParameters(transactionIndex, functionsModel.get(functionComboBox.currentIndex).text);
for (var p = 0; p < parameters.length; p++) {
paramsModel.append({ name: parameters[p].name, type: parameters[p].type, value: parameters[p].value });
}
}
}
GridLayout {
id: dialogContent
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: qsTr("Title")
}
TextField {
id: titleField
focus: true
Layout.fillWidth: true
}
Label {
text: qsTr("Function")
}
ComboBox {
id: functionComboBox
Layout.fillWidth: true
currentIndex: -1
textRole: "text"
editable: false
model: ListModel {
id: functionsModel
}
onCurrentIndexChanged: {
loadParameters();
}
}
Label {
text: qsTr("Value")
}
TextField {
id: valueField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas")
}
TextField {
id: gasField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas price")
}
TextField {
id: gasPriceField
Layout.fillWidth: true
}
Label {
text: qsTr("Parameters")
}
TableView {
model: paramsModel
Layout.fillWidth: true
TableViewColumn {
role: "name"
title: "Name"
width: 120
}
TableViewColumn {
role: "type"
title: "Type"
width: 120
}
TableViewColumn {
role: "value"
title: "Value"
width: 120
}
itemDelegate: {
return editableDelegate;
}
}
}
RowLayout
{
anchors.bottom: parent.bottom
anchors.right: parent.right;
Button {
text: qsTr("Ok");
onClicked: {
close();
accepted();
}
}
Button {
text: qsTr("Cancel");
onClicked: close();
}
}
ListModel {
id: paramsModel
}
Component {
id: editableDelegate
Item {
Text {
width: parent.width
anchors.margins: 4
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
elide: styleData.elideMode
text: styleData.value !== undefined ? styleData.value : ""
color: styleData.textColor
visible: !styleData.selected
}
Loader {
id: loaderEditor
anchors.fill: parent
anchors.margins: 4
Connections {
target: loaderEditor.item
onTextChanged: {
paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text);
}
}
sourceComponent: (styleData.selected) ? editor : null
Component {
id: editor
TextInput {
id: textinput
color: styleData.textColor
text: styleData.value
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}
}
}
}

89
mix/qml/TransactionList.qml

@ -0,0 +1,89 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Rectangle {
color: "transparent"
id: transactionListContainer
focus: true
anchors.topMargin: 10
anchors.left: parent.left
height: parent.height
width: parent.width
ListView {
anchors.top: parent.top
height: parent.height
width: parent.width
id: transactionList
model: transactionListModel
delegate: renderDelegate
}
Button {
anchors.bottom: parent.bottom
text: qsTr("Add")
onClicked:
{
// Set next id here to work around Qt bug
// https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handle would just edit the item that was just created, no harm done
transactionDialog.reset(transactionListModel.count, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
TransactionDialog {
id: transactionDialog
onAccepted: {
transactionListModel.edit(transactionDialog);
}
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
RowLayout
{
anchors.fill: parent
Text {
//anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
text: title
font.pointSize: 12
verticalAlignment: Text.AlignBottom
}
ToolButton {
text: qsTr("Edit");
Layout.fillHeight: true
onClicked: {
transactionDialog.reset(index, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
ToolButton {
text: qsTr("Delete");
Layout.fillHeight: true
onClicked: {
}
}
ToolButton {
text: qsTr("Run");
Layout.fillHeight: true
onClicked: {
transactionListModel.runTransaction(index);
}
}
}
}
}
}

10
mix/qml/js/Debugger.js

@ -8,6 +8,7 @@ function init()
{
currentSelectedState = 0;
select(currentSelectedState);
displayReturnValue();
}
function moveSelection(incr)
@ -30,7 +31,7 @@ function select(stateIndex)
var state = debugStates[stateIndex];
var codeStr = bytesCodeMapping.getValue(state.curPC);
highlightSelection(codeStr);
currentSelectedState = codeStr;
currentSelectedState = stateIndex;
completeCtxInformation(state);
levelList.model = state.levels;
levelList.update();
@ -38,7 +39,6 @@ function select(stateIndex)
function highlightSelection(index)
{
console.log(index);
statesList.currentIndex = index;
}
@ -60,3 +60,9 @@ function endOfDebug()
debugMemoryTxt.text = state.endOfDebug;
headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft;
}
function displayReturnValue()
{
headerReturnList.model = contractCallReturnParameters;
headerReturnList.update();
}

6
mix/qml/main.qml

@ -9,8 +9,6 @@ import CodeEditorExtensionManager 1.0
ApplicationWindow {
id: mainApplication
visible: true
x: Screen.width / 2 - width / 2
y: Screen.height / 2 - height / 2
width: 1200
height: 600
minimumWidth: 400
@ -26,6 +24,10 @@ ApplicationWindow {
}
}
}
Component.onCompleted: {
setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2);
}
MainContent {
}

4
test/stSystemOperationsTestFiller.json

@ -740,7 +740,7 @@
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "365223",
"gasLimit" : "365243",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
@ -774,7 +774,7 @@
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "365224",
"gasLimit" : "365244",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",

65
test/trie.cpp

@ -50,7 +50,7 @@ static unsigned fac(unsigned _i)
BOOST_AUTO_TEST_SUITE(TrieTests)
BOOST_AUTO_TEST_CASE(trie_tests)
BOOST_AUTO_TEST_CASE(trie_test_anyorder)
{
string testPath = test::getTestPath();
@ -92,6 +92,69 @@ BOOST_AUTO_TEST_CASE(trie_tests)
}
}
BOOST_AUTO_TEST_CASE(trie_tests_ordered)
{
string testPath = test::getTestPath();
testPath += "/TrieTests";
cnote << "Testing Trie...";
js::mValue v;
string s = asString(contents(testPath + "/trietest.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?");
js::read_string(s, v);
for (auto& i: v.get_obj())
{
cnote << i.first;
js::mObject& o = i.second.get_obj();
vector<pair<string, string>> ss;
vector<string> keysToBeDeleted;
for (auto& i: o["in"].get_array())
{
vector<string> values;
for (auto& s: i.get_array())
{
if (s.type() == json_spirit::str_type)
values.push_back(s.get_str());
else if (s.type() == json_spirit::null_type)
{
// mark entry for deletion
values.push_back("");
if (!values[0].find("0x"))
values[0] = asString(fromHex(values[0].substr(2)));
keysToBeDeleted.push_back(values[0]);
}
else
BOOST_FAIL("Bad type (expected string)");
}
BOOST_REQUIRE(values.size() == 2);
ss.push_back(make_pair(values[0], values[1]));
if (!ss.back().first.find("0x"))
ss.back().first = asString(fromHex(ss.back().first.substr(2)));
if (!ss.back().second.find("0x"))
ss.back().second = asString(fromHex(ss.back().second.substr(2)));
}
MemoryDB m;
GenericTrieDB<MemoryDB> t(&m);
t.init();
BOOST_REQUIRE(t.check(true));
for (auto const& k: ss)
{
if (find(keysToBeDeleted.begin(), keysToBeDeleted.end(), k.first) != keysToBeDeleted.end() && k.second.empty())
t.remove(k.first);
else
t.insert(k.first, k.second);
BOOST_REQUIRE(t.check(true));
}
BOOST_REQUIRE(!o["root"].is_null());
BOOST_CHECK_EQUAL(o["root"].get_str(), "0x" + toHex(t.root().asArray()));
}
}
inline h256 stringMapHash256(StringMap const& _s)
{
return hash256(_s);

2392
test/vmArithmeticTestFiller.json

File diff suppressed because it is too large
Loading…
Cancel
Save