Browse Source

Merge branch 'develop' into p2p

cl-refactor
subtly 10 years ago
parent
commit
d8836b2c68
  1. 20
      CodingStandards.txt
  2. 158
      alethzero/MainWin.cpp
  3. 13
      alethzero/MainWin.h
  4. 103
      alethzero/NatspecHandler.cpp
  5. 58
      alethzero/NatspecHandler.h
  6. 50
      alethzero/OurWebThreeStubServer.cpp
  7. 8
      alethzero/OurWebThreeStubServer.h
  8. 4
      evmjit/libevmjit/Compiler.cpp
  9. 11
      evmjit/libevmjit/Ext.cpp
  10. 4
      evmjit/libevmjit/Ext.h
  11. 8
      exp/main.cpp
  12. 3
      libdevcore/CommonData.h
  13. 20
      libdevcore/CommonIO.cpp
  14. 3
      libdevcore/CommonIO.h
  15. 2
      libdevcore/CommonJS.h
  16. 2
      libdevcrypto/CryptoPP.cpp
  17. 2
      libethereum/Executive.cpp
  18. 30
      libethereum/State.cpp
  19. 6
      libethereum/State.h
  20. 4
      libjsqrc/ethereumjs/dist/ethereum.js
  21. 2
      libjsqrc/ethereumjs/dist/ethereum.js.map
  22. 2
      libjsqrc/ethereumjs/dist/ethereum.min.js
  23. 77
      libjsqrc/ethereumjs/example/natspec_contract.html
  24. 4
      libjsqrc/ethereumjs/lib/abi.js
  25. 2
      libqwebthree/QWebThree.cpp
  26. 5
      libsolidity/Compiler.cpp
  27. 2
      libsolidity/Compiler.h
  28. 13
      libsolidity/CompilerStack.cpp
  29. 8
      libsolidity/CompilerStack.h
  30. 9
      libsolidity/ExpressionCompiler.cpp
  31. 4
      libsolidity/InterfaceHandler.cpp
  32. 4
      libsolidity/Token.h
  33. 4
      libsolidity/Types.cpp
  34. 2
      libsolidity/Types.h
  35. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  36. 7
      mix/AssemblyDebuggerControl.cpp
  37. 6
      mix/AssemblyDebuggerControl.h
  38. 2
      mix/ClientModel.cpp
  39. 21
      mix/CodeEditorExtensionManager.cpp
  40. 14
      mix/CodeEditorExtensionManager.h
  41. 24
      mix/CodeModel.cpp
  42. 24
      mix/CodeModel.h
  43. 94
      mix/ConstantCompilationControl.cpp
  44. 118
      mix/DebuggingStateWrapper.cpp
  45. 30
      mix/DebuggingStateWrapper.h
  46. 4
      mix/Extension.h
  47. 24
      mix/StateListView.cpp
  48. 66
      mix/StatusPane.cpp
  49. 13
      mix/StatusPane.h
  50. 21
      mix/qml.qrc
  51. 35
      mix/qml/DebugBasicInfo.qml
  52. 83
      mix/qml/DebugInfoList.qml
  53. 689
      mix/qml/Debugger.qml
  54. 71
      mix/qml/ItemDelegateDataDump.qml
  55. 196
      mix/qml/MainContent.qml
  56. 7
      mix/qml/StateList.qml
  57. 116
      mix/qml/StatusPane.qml
  58. 39
      mix/qml/StepActionImage.qml
  59. BIN
      mix/qml/img/bugiconactive.png
  60. BIN
      mix/qml/img/bugiconinactive.png
  61. BIN
      mix/qml/img/closedtriangleindicator.png
  62. BIN
      mix/qml/img/jumpintoback.png
  63. BIN
      mix/qml/img/jumpintobackdisabled.png
  64. BIN
      mix/qml/img/jumpintoforward.png
  65. BIN
      mix/qml/img/jumpintoforwarddisabled.png
  66. BIN
      mix/qml/img/jumpoutback.png
  67. BIN
      mix/qml/img/jumpoutbackdisabled.png
  68. BIN
      mix/qml/img/jumpoutforward.png
  69. BIN
      mix/qml/img/jumpoutforwarddisabled.png
  70. BIN
      mix/qml/img/jumpoverback.png
  71. BIN
      mix/qml/img/jumpoverbackdisabled.png
  72. BIN
      mix/qml/img/jumpoverforward.png
  73. BIN
      mix/qml/img/opentriangleindicator.png
  74. 147
      mix/qml/js/Debugger.js
  75. 27
      mix/qml/js/ErrorLocationFormater.js
  76. 19
      mix/qml/main.qml
  77. 4
      standard.js
  78. 16
      test/SolidityEndToEndTest.cpp
  79. 42
      test/SolidityNatspecJSON.cpp
  80. 17
      test/vm.cpp
  81. 36
      test/vmSystemOperationsTestFiller.json

20
CodingStandards.txt

@ -128,6 +128,10 @@ d. Use override, final and const judiciously.
e. No implementations with the class declaration, except:
- template or force-inline method (though prefer implementation at bottom of header file).
- one-line implementation (in which case include it in same line as declaration).
f. For a method 'foo'
- Member: m_foo;
- Getter: foo() [ also: for booleans, isFoo() ];
- Setter: setFoo();
@ -162,3 +166,19 @@ d. In general expressions should be roughly as important/semantically meaningful
a. Comments should be doxygen-compilable, using @notation rather than \notation.
12. Include Headers
a. Includes should go in order of lower level (STL -> boost -> libdevcore -> libdevcrypto -> libethcore -> libethereum) to higher level. Lower levels are basically dependencies to the higher levels. For example:
#include <string>
#include <boost/filesystem.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h>
#include <libdevcrypto/SHA3.h>
#include <libethereum/Defaults.h>
b. The only exception to the above rule is the top of a .cpp file where its corresponding header should be located.

158
alethzero/MainWin.cpp

@ -37,7 +37,7 @@
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
@ -48,10 +48,10 @@
#include <libethereum/EthereumHost.h>
#include <libethereum/DownloadMan.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include "MainWin.h"
#include "DownloadView.h"
#include "MiningView.h"
#include "BuildInfo.h"
#include "MainWin.h"
#include "OurWebThreeStubServer.h"
#include "ui_Main.h"
using namespace std;
@ -66,11 +66,11 @@ static void initUnits(QComboBox* _b)
_b->addItem(QString::fromStdString(units()[n].second), n);
}
QString Main::fromRaw(dev::h256 _n, unsigned* _inc)
QString Main::fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
std::string s((char const*)_n.data(), 32);
string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return QString();
@ -91,13 +91,13 @@ QString Main::fromRaw(dev::h256 _n, unsigned* _inc)
return QString();
}
static std::vector<dev::KeyPair> keysAsVector(QList<dev::KeyPair> const& keys)
static vector<KeyPair> keysAsVector(QList<KeyPair> const& keys)
{
auto list = keys.toStdList();
return {begin(list), end(list)};
}
static QString contentsOfQResource(std::string const& res)
static QString contentsOfQResource(string const& res)
{
QFile file(QString::fromStdString(res));
if (!file.open(QFile::ReadOnly))
@ -116,7 +116,7 @@ Main::Main(QWidget *parent) :
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
g_logPost = [=](std::string const& s, char const* c)
g_logPost = [=](string const& s, char const* c)
{
simpleDebugOut(s, c);
m_logLock.lock();
@ -136,8 +136,8 @@ Main::Main(QWidget *parent) :
cerr << "Block Hash: " << BlockChain::genesis().hash << endl;
cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << endl;
cerr << "Network protocol version: " << dev::eth::c_protocolVersion << endl;
cerr << "Client database version: " << dev::eth::c_databaseVersion << endl;
cerr << "Network protocol version: " << c_protocolVersion << endl;
cerr << "Client database version: " << c_databaseVersion << endl;
ui->configDock->close();
on_verbosity_valueChanged();
@ -158,7 +158,7 @@ Main::Main(QWidget *parent) :
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"}));
m_qwebConnector.reset(new QWebThreeConnector());
m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys)));
m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys), this));
connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString)));
m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening();
@ -234,7 +234,7 @@ void Main::addNewId(QString _ids)
refreshWhisper();
}
dev::p2p::NetworkPreferences Main::netPrefs() const
NetworkPreferences Main::netPrefs() const
{
return NetworkPreferences(ui->port->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), ui->localNetworking->isChecked());
}
@ -244,7 +244,7 @@ void Main::onKeysChanged()
installBalancesWatch();
}
unsigned Main::installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f)
unsigned Main::installWatch(LogFilter const& _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf);
m_handlers[ret] = _f;
@ -266,10 +266,10 @@ void Main::uninstallWatch(unsigned _w)
void Main::installWatches()
{
installWatch(dev::eth::LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(dev::eth::LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(dev::eth::PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(dev::eth::ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
}
Address Main::getNameReg() const
@ -279,24 +279,24 @@ Address Main::getNameReg() const
Address Main::getCurrencies() const
{
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)2)));
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)));
}
void Main::installNameRegWatch()
{
uninstallWatch(m_nameRegFilter);
m_nameRegFilter = installWatch(dev::eth::LogFilter().address((u160)getNameReg()), [=](LocalisedLogEntries const&){ onNameRegChange(); });
m_nameRegFilter = installWatch(LogFilter().address((u160)getNameReg()), [=](LocalisedLogEntries const&){ onNameRegChange(); });
}
void Main::installCurrenciesWatch()
{
uninstallWatch(m_currenciesFilter);
m_currenciesFilter = installWatch(dev::eth::LogFilter().address((u160)getCurrencies()), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
m_currenciesFilter = installWatch(LogFilter().address((u160)getCurrencies()), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
}
void Main::installBalancesWatch()
{
dev::eth::LogFilter tf;
LogFilter tf;
vector<Address> altCoins;
Address coinsAddr = getCurrencies();
@ -343,6 +343,9 @@ void Main::onNewBlock()
refreshBlockCount();
refreshBlockChain();
refreshAccounts();
// We must update balances since we can't filter updates to basic accounts.
refreshBalances();
}
void Main::onNewPending()
@ -467,7 +470,7 @@ static Public stringToPublic(QString const& _a)
QString Main::pretty(dev::Address _a) const
{
/* static std::map<Address, QString> s_memos;
/* static map<Address, QString> s_memos;
if (!s_memos.count(_a))
{*/
@ -505,7 +508,7 @@ QString Main::render(dev::Address _a) const
return QString::fromStdString(_a.abridged());
}
string32 fromString(std::string const& _s)
string32 fromString(string const& _s)
{
string32 ret;
for (unsigned i = 0; i < 32 && i <= _s.size(); ++i)
@ -518,7 +521,7 @@ Address Main::fromString(QString const& _n) const
if (_n == "(Create Contract)")
return Address();
/* static std::map<QString, Address> s_memos;
/* static map<QString, Address> s_memos;
if (!s_memos.count(_n))
{*/
@ -860,18 +863,18 @@ void Main::on_preview_triggered()
void Main::refreshMining()
{
dev::eth::MineProgress p = ethereum()->miningProgress();
MineProgress p = ethereum()->miningProgress();
ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining");
if (!ui->miningView->isVisible())
return;
list<dev::eth::MineInfo> l = ethereum()->miningHistory();
list<MineInfo> l = ethereum()->miningHistory();
static unsigned lh = 0;
if (p.hashes < lh)
ui->miningView->resetStats();
lh = p.hashes;
ui->miningView->appendStats(l, p);
/* if (p.ms)
for (dev::eth::MineInfo const& i: l)
for (MineInfo const& i: l)
cnote << i.hashes * 10 << "h/sec, need:" << i.requirement << " best:" << i.best << " best-so-far:" << p.best << " avg-speed:" << (p.hashes * 1000 / p.ms) << "h/sec";
*/
}
@ -1026,10 +1029,10 @@ void Main::refreshBlockCount()
cwatch << "refreshBlockCount()";
auto d = ethereum()->blockChain().details();
auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty;
ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet"));
ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet"));
}
static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 _h, BlockChain const& _bc)
static bool blockMatch(string const& _f, BlockDetails const& _b, h256 _h, BlockChain const& _bc)
{
try
{
@ -1178,7 +1181,7 @@ void Main::timerEvent(QTimerEvent*)
}
}
string Main::renderDiff(dev::eth::StateDiff const& _d) const
string Main::renderDiff(StateDiff const& _d) const
{
stringstream s;
@ -1187,24 +1190,24 @@ string Main::renderDiff(dev::eth::StateDiff const& _d) const
{
s << "<hr/>";
dev::eth::AccountDiff const& ad = i.second;
AccountDiff const& ad = i.second;
s << "<code style=\"white-space: pre; font-weight: bold\">" << lead(ad.changeType()) << " </code>" << " <b>" << render(i.first).toStdString() << "</b>";
if (!ad.exist.to())
continue;
if (ad.balance)
{
s << "<br/>" << indent << "Balance " << std::dec << formatBalance(ad.balance.to());
s << " <b>" << std::showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << std::noshowpos << "</b>";
s << "<br/>" << indent << "Balance " << dec << formatBalance(ad.balance.to());
s << " <b>" << showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << noshowpos << "</b>";
}
if (ad.nonce)
{
s << "<br/>" << indent << "Count #" << std::dec << ad.nonce.to();
s << " <b>" << std::showpos << (((dev::bigint)ad.nonce.to()) - ((dev::bigint)ad.nonce.from())) << std::noshowpos << "</b>";
s << "<br/>" << indent << "Count #" << dec << ad.nonce.to();
s << " <b>" << showpos << (((dev::bigint)ad.nonce.to()) - ((dev::bigint)ad.nonce.from())) << noshowpos << "</b>";
}
if (ad.code)
{
s << "<br/>" << indent << "Code " << std::hex << ad.code.to().size() << " bytes";
s << "<br/>" << indent << "Code " << hex << ad.code.to().size() << " bytes";
if (ad.code.from().size())
s << " (" << ad.code.from().size() << " bytes)";
}
@ -1226,7 +1229,7 @@ string Main::renderDiff(dev::eth::StateDiff const& _d) const
else if (i.first > u160(1) << 150)
s << (h160)(u160)i.first;
else
s << std::hex << i.first;
s << hex << i.first;
*/
if (!i.second.from())
s << ": " << prettyU256(i.second.to()).toStdString();
@ -1479,10 +1482,10 @@ void Main::populateDebugger(dev::bytesConstRef _r)
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, dev::eth::VM* voidVM, dev::eth::ExtVMFace const* voidExt)
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, VM* voidVM, ExtVMFace const* voidExt)
{
dev::eth::VM& vm = *voidVM;
dev::eth::ExtVM const& ext = *static_cast<dev::eth::ExtVM const*>(voidExt);
VM& vm = *voidVM;
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
if (ext.code != lastExtCode)
{
lastExtCode = ext.code;
@ -1605,11 +1608,11 @@ static shh::Topic topicFromText(QString _s)
{
u256 v(d.cap(2).toStdString());
if (d.cap(6) == "szabo")
v *= dev::eth::szabo;
v *= szabo;
else if (d.cap(5) == "finney")
v *= dev::eth::finney;
v *= finney;
else if (d.cap(4) == "ether")
v *= dev::eth::ether;
v *= ether;
bytes bs = dev::toCompactBigEndian(v);
if (d.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
@ -1635,6 +1638,29 @@ static shh::Topic topicFromText(QString _s)
return ret;
}
bool Main::sourceIsSolidity(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol");
}
string const Main::getFunctionHashes(dev::solidity::CompilerStack const &_compiler,
string const& _contractName)
{
string ret = "";
auto const& contract = _compiler.getContractDefinition(_contractName);
auto interfaceFunctions = contract.getInterfaceFunctions();
for (auto const& it: interfaceFunctions)
{
ret += it.first.abridged();
ret += " :";
ret += it.second->getName() + "\n";
}
return ret;
}
void Main::on_data_textChanged()
{
m_pcWarp.clear();
@ -1648,7 +1674,7 @@ void Main::on_data_textChanged()
{
m_data = fromHex(src);
}
else if (src.substr(0, 8) == "contract" || src.substr(0, 5) == "//sol") // improve this heuristic
else if (sourceIsSolidity(src))
{
dev::solidity::CompilerStack compiler;
try
@ -1657,6 +1683,7 @@ void Main::on_data_textChanged()
solidity = "<h4>Solidity</h4>";
solidity += "<pre>" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + "</pre>";
solidity += "<pre>" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "</pre>";
solidity += "<pre>" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "</pre>";
}
catch (dev::Exception const& exception)
{
@ -1671,7 +1698,7 @@ void Main::on_data_textChanged()
}
else
{
m_data = dev::eth::compileLLL(src, m_enableOptimizer, &errors);
m_data = compileLLL(src, m_enableOptimizer, &errors);
if (errors.size())
{
try
@ -1687,11 +1714,11 @@ void Main::on_data_textChanged()
}
else
{
auto asmcode = dev::eth::compileLLLToAsm(src, false);
auto asmcode = compileLLLToAsm(src, false);
lll = "<h4>Pre</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>";
if (m_enableOptimizer)
{
asmcode = dev::eth::compileLLLToAsm(src, true);
asmcode = compileLLLToAsm(src, true);
lll = "<h4>Opt</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>" + lll;
}
}
@ -1872,7 +1899,28 @@ void Main::on_send_clicked()
debugFinished();
Secret s = i.secret();
if (isCreation())
{
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
ethereum()->transact(s, value(), m_data, ui->gas->value(), gasPrice());
string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src))
try
{
dev::solidity::CompilerStack compiler;
m_data = compiler.compile(src, m_enableOptimizer);
for (string& s: compiler.getContractNames())
{
h256 contractHash = compiler.getContractCodeHash(s);
m_natspecDB.add(contractHash,
compiler.getMetadata(s, dev::solidity::DocumentationType::NATSPEC_USER));
}
}
catch (...)
{
statusBar()->showMessage("Couldn't compile Solidity Contract.");
}
}
else
ethereum()->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
return;
@ -2008,7 +2056,7 @@ void Main::on_dumpTracePretty_triggered()
f << " STORAGE" << endl;
for (auto const& i: ws.storage)
f << showbase << hex << i.first << ": " << i.second << endl;
f << dec << ws.levels.size() << " | " << ws.cur << " | #" << ws.steps << " | " << hex << setw(4) << setfill('0') << ws.curPC << " : " << dev::eth::instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
f << dec << ws.levels.size() << " | " << ws.cur << " | #" << ws.steps << " | " << hex << setw(4) << setfill('0') << ws.curPC << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
}
}
@ -2095,7 +2143,9 @@ QString Main::prettyU256(dev::u256 _n) const
unsigned inc = 0;
QString raw;
ostringstream s;
if (!(_n >> 64))
if (_n > szabo && _n < 1000000 * ether)
s << "<span style=\"color: #215\">" << formatBalance(_n) << "</span> <span style=\"color: #448\">(0x" << hex << (uint64_t)_n << ")</span>";
else if (!(_n >> 64))
s << "<span style=\"color: #008\">" << (uint64_t)_n << "</span> <span style=\"color: #448\">(0x" << hex << (uint64_t)_n << ")</span>";
else if (!~(_n >> 64))
s << "<span style=\"color: #008\">" << (int64_t)_n << "</span> <span style=\"color: #448\">(0x" << hex << (int64_t)_n << ")</span>";
@ -2235,7 +2285,7 @@ void Main::updateDebugger()
cwarn << "PC (" << (unsigned)ws.curPC << ") is after code range (" << m_codes[ws.code].size() << ")";
ostringstream ss;
ss << dec << "STEP: " << ws.steps << " | PC: 0x" << hex << ws.curPC << " : " << dev::eth::instructionInfo(ws.inst).name << " | ADDMEM: " << dec << ws.newMemSize << " words | COST: " << dec << ws.gasCost << " | GAS: " << dec << ws.gas;
ss << dec << "STEP: " << ws.steps << " | PC: 0x" << hex << ws.curPC << " : " << instructionInfo(ws.inst).name << " | ADDMEM: " << dec << ws.newMemSize << " words | COST: " << dec << ws.gasCost << " | GAS: " << dec << ws.gas;
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
stringstream s;
for (auto const& i: ws.storage)
@ -2257,6 +2307,16 @@ void Main::on_post_clicked()
whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value()));
}
string Main::lookupNatSpec(dev::h256 const& _contractHash) const
{
return m_natspecDB.retrieve(_contractHash);
}
string Main::lookupNatSpecUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData)
{
return m_natspecDB.getUserNotice(_contractHash, _transactionData);
}
void Main::refreshWhispers()
{
ui->whispers->clear();

13
alethzero/MainWin.h

@ -36,6 +36,9 @@
#include <libethereum/Executive.h>
#include <libqwebthree/QWebThree.h>
#include <libwebthree/WebThree.h>
#include <libsolidity/CompilerStack.h>
#include "NatspecHandler.h"
namespace Ui {
class Main;
@ -80,7 +83,8 @@ public:
dev::eth::Client* ethereum() const { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); }
std::string lookupNatSpec(dev::h256 const& _contractCode) const { (void)_contractCode; return ""; } // TODO: actually implement with leveldb & a UI.
std::string lookupNatSpec(dev::h256 const& _contractHash) const;
std::string lookupNatSpecUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData);
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
@ -227,6 +231,12 @@ private:
void refreshBlockCount();
void refreshBalances();
/// Attempts to infer that @c _source contains Solidity code
bool sourceIsSolidity(std::string const& _source);
/// @eturns all method hashes of a Solidity contract in a string
std::string const getFunctionHashes(dev::solidity::CompilerStack const &_compiler,
std::string const& _contractName = "");
std::unique_ptr<Ui::Main> ui;
std::unique_ptr<dev::WebThreeDirect> m_webThree;
@ -269,4 +279,5 @@ private:
QWebThree* m_qweb = nullptr;
static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr);
NatspecHandler m_natspecDB;
};

103
alethzero/NatspecHandler.cpp

@ -0,0 +1,103 @@
/*
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 NatspecHandler.cpp
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*/
#include "NatspecHandler.h"
#include <string>
#include <boost/filesystem.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h>
#include <libdevcrypto/SHA3.h>
#include <libethereum/Defaults.h>
using namespace dev;
using namespace dev::eth;
using namespace std;
NatspecHandler::NatspecHandler()
{
string path = Defaults::dbPath();
boost::filesystem::create_directories(path);
ldb::Options o;
o.create_if_missing = true;
ldb::DB::Open(o, path + "/natspec", &m_db);
}
NatspecHandler::~NatspecHandler()
{
delete m_db;
}
void NatspecHandler::add(dev::h256 const& _contractHash, string const& _doc)
{
bytes k = _contractHash.asBytes();
string v = _doc;
m_db->Put(m_writeOptions, ldb::Slice((char const*)k.data(), k.size()), ldb::Slice((char const*)v.data(), v.size()));
}
string NatspecHandler::retrieve(dev::h256 const& _contractHash) const
{
bytes k = _contractHash.asBytes();
string ret;
m_db->Get(m_readOptions, ldb::Slice((char const*)k.data(), k.size()), &ret);
return ret;
}
string NatspecHandler::getUserNotice(string const& json, dev::bytes const& _transactionData)
{
Json::Value natspec;
Json::Value userNotice;
string retStr;
m_reader.parse(json, natspec);
bytes transactionFunctionPart(_transactionData.begin(), _transactionData.begin() + 4);
FixedHash<4> transactionFunctionHash(transactionFunctionPart);
Json::Value methods = natspec["methods"];
for (Json::ValueIterator it = methods.begin(); it != methods.end(); ++it)
{
Json::Value keyValue = it.key();
if (!keyValue.isString())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected"));
string functionSig = keyValue.asString();
FixedHash<4> functionHash(dev::sha3(functionSig));
if (functionHash == transactionFunctionHash)
{
Json::Value val = (*it)["notice"];
if (!val.isString())
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Illegal Natspec JSON detected"));
return val.asString();
}
}
// not found
return string();
}
string NatspecHandler::getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData)
{
return getUserNotice(retrieve(_contractHash), _transactionData);
}

58
alethzero/NatspecHandler.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 NatspecHandler.h
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*/
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <jsoncpp/json/json.h>
#include <libdevcore/FixedHash.h>
namespace ldb = leveldb;
class NatspecHandler
{
public:
NatspecHandler();
~NatspecHandler();
/// Stores locally in a levelDB a key value pair of contract code hash to natspec documentation
void add(dev::h256 const& _contractHash, std::string const& _doc);
/// Retrieves the natspec documentation as a string given a contract code hash
std::string retrieve(dev::h256 const& _contractHash) const;
/// Given a json natspec string and the transaction data return the user notice
std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData);
/// Given a contract code hash and the transaction's data retrieve the natspec documention's
/// user notice for that transaction.
/// @returns The user notice or an empty string if no natspec for the contract exists
/// or if the existing natspec does not document the @c _methodName
std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta);
private:
ldb::ReadOptions m_readOptions;
ldb::WriteOptions m_writeOptions;
ldb::DB* m_db;
Json::Reader m_reader;
};

50
alethzero/OurWebThreeStubServer.cpp

@ -22,14 +22,17 @@
#include "OurWebThreeStubServer.h"
#include <QMessageBox>
#include <QAbstractButton>
#include <libwebthree/WebThree.h>
#include "MainWin.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts):
WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3)
OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3,
std::vector<dev::KeyPair> const& _accounts, Main* main):
WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3), m_main(main)
{}
std::string OurWebThreeStubServer::shh_newIdentity()
@ -39,36 +42,31 @@ std::string OurWebThreeStubServer::shh_newIdentity()
return toJS(kp.pub());
}
bool OurWebThreeStubServer::authenticate(dev::TransactionSkeleton const& _t) const
bool OurWebThreeStubServer::showAuthenticationPopup(std::string const& _title, std::string const& _text) const
{
return true;
// To get the balance of the sender
cnote << "Sender has ETH: " << m_web3->ethereum()->postState().balance(_t.from);
Main* main; // don't know this yet, should be a member and set at construction time by Main, who will construct us.
QMessageBox userInput;
userInput.setText(QString::fromStdString(_title));
userInput.setInformativeText(QString::fromStdString(_text + "\n Do you wish to allow this?"));
userInput.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
userInput.button(QMessageBox::Ok)->setText("Allow");
userInput.button(QMessageBox::Cancel)->setText("Reject");
userInput.setDefaultButton(QMessageBox::Cancel);
return userInput.exec() == QMessageBox::Ok;
}
bool OurWebThreeStubServer::authenticate(dev::TransactionSkeleton const& _t) const
{
h256 contractCodeHash = m_web3->ethereum()->postState().codeHash(_t.to);
if (contractCodeHash == EmptySHA3)
{
// recipient has no code - nothing special about this transaction.
// TODO: show basic message for value transfer.
return true; // or whatever.
}
std::string natspecJson = main->lookupNatSpec(contractCodeHash);
if (natspecJson.empty())
{
// TODO: HUGE warning - we don't know what this will do!
return false; // or whatever.
}
// otherwise it's a transaction to contract for which we have the natspec:
// determine the actual message (embellish with real data) and ask user.
return true;
// QMessageBox::question();
std::string userNotice = m_main->lookupNatSpecUserNotice(contractCodeHash, _t.data);
if (userNotice.empty())
return showAuthenticationPopup("Unverified Pending Transaction",
"An undocumented transaction is about to be executed.");
return true;
// otherwise it's a transaction to a contract for which we have the natspec
return showAuthenticationPopup("Pending Transaction", userNotice);
}

8
alethzero/OurWebThreeStubServer.h

@ -24,12 +24,15 @@
#include <libdevcrypto/Common.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
class Main;
class OurWebThreeStubServer: public QObject, public WebThreeStubServer
{
Q_OBJECT
public:
OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts);
OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3,
std::vector<dev::KeyPair> const& _accounts, Main* main);
virtual std::string shh_newIdentity() override;
virtual bool authenticate(dev::TransactionSkeleton const& _t) const;
@ -38,5 +41,8 @@ signals:
void onNewId(QString _s);
private:
bool showAuthenticationPopup(std::string const& _title, std::string const& _text) const;
dev::WebThreeDirect* m_web3;
Main* m_main;
};

4
evmjit/libevmjit/Compiler.cpp

@ -644,7 +644,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
case Instruction::EXTCODESIZE:
{
auto addr = stack.pop();
auto codeRef = _ext.getExtCode(addr);
auto codeRef = _ext.extcode(addr);
stack.push(codeRef.size);
break;
}
@ -682,7 +682,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
auto srcIdx = stack.pop();
auto reqBytes = stack.pop();
auto codeRef = _ext.getExtCode(addr);
auto codeRef = _ext.extcode(addr);
_memory.copyBytes(codeRef.ptr, codeRef.size, srcIdx, destMemIdx, reqBytes);
break;

11
evmjit/libevmjit/Ext.cpp

@ -22,9 +22,12 @@ namespace jit
Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
RuntimeHelper(_runtimeManager),
m_memoryMan(_memoryMan),
m_memoryMan(_memoryMan)
#ifdef __MSCVER
,
m_funcs({}), // The only std::array initialization that works in both Visual Studio & GCC
m_argAllocas({})
#endif
{
m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size");
}
@ -48,7 +51,7 @@ std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})},
FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_getExtCode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
FuncDesc{"ext_calldataload", getFunctionType(Type::Void, {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr})},
}};
@ -166,10 +169,10 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
return hash;
}
MemoryRef Ext::getExtCode(llvm::Value* _addr)
MemoryRef Ext::extcode(llvm::Value* _addr)
{
auto addr = Endianness::toBE(m_builder, _addr);
auto code = createCall(EnvFunc::getExtCode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size});
auto code = createCall(EnvFunc::extcode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size});
auto codeSize = m_builder.CreateLoad(m_size);
auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word);
return {code, codeSize256};

4
evmjit/libevmjit/Ext.h

@ -34,7 +34,7 @@ enum class EnvFunc
call,
log,
blockhash,
getExtCode,
extcode,
calldataload, // Helper function, not client Env interface
_size
@ -55,7 +55,7 @@ public:
llvm::Value* blockhash(llvm::Value* _number);
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);
MemoryRef getExtCode(llvm::Value* _addr);
MemoryRef extcode(llvm::Value* _addr);
void log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Value*,4> const& _topics);

8
exp/main.cpp

@ -75,7 +75,7 @@ int main()
cnote << i;*/
return 0;
}
#else
#elif 0
int main()
{
KeyPair u = KeyPair::create();
@ -95,5 +95,11 @@ int main()
cnote << "State after transaction: " << s;
cnote << before.diff(s);
}
#else
int main()
{
cnote << KeyPair(Secret("0000000000000000000000000000000000000000000000000000000000000000")).address();
cnote << KeyPair(Secret("1111111111111111111111111111111111111111111111111111111111111111")).address();
}
#endif

3
libdevcore/CommonData.h

@ -110,6 +110,9 @@ inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toB
inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; }
inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; }
/// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val) { return toHex(toBigEndian(val)); }
/// Convenience function for toBigEndian.
/// @returns a byte array just big enough to represent @a _val.
template <class _T>

20
libdevcore/CommonIO.cpp

@ -26,30 +26,30 @@
using namespace std;
using namespace dev;
string dev::memDump(bytes const& _b, unsigned _w, bool _html)
string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
{
stringstream ret;
if (_html)
ret << "<pre style=\"font-family: Monospace,Lucida Console,Courier,Courier New,sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
for (unsigned i = 0; i < _bytes.size(); i += _width)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 127)
if ((char)_b[j] == '<' && _html)
for (unsigned j = i; j < i + _width; ++j)
if (j < _bytes.size())
if (_bytes[j] >= 32 && _bytes[j] < 127)
if ((char)_bytes[j] == '<' && _html)
ret << "&lt;";
else if ((char)_b[j] == '&' && _html)
else if ((char)_bytes[j] == '&' && _html)
ret << "&amp;";
else
ret << (char)_b[j];
ret << (char)_bytes[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_bytes[j] << " ";
ret << "\n";
}
if (_html)

3
libdevcore/CommonIO.h

@ -47,7 +47,8 @@ bytes contents(std::string const& _file);
void writeFile(std::string const& _file, bytes const& _data);
/// Nicely renders the given bytes to a string, optionally as HTML.
std::string memDump(bytes const& _b, unsigned _w = 8, bool _html = false);
/// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line.
std::string memDump(bytes const& _bytes, unsigned _width = 8, bool _html = false);
// Stream I/O functions.
// Provides templated stream I/O for all STL collections so they can be shifted on to any iostream-like interface.

2
libdevcore/CommonJS.h

@ -65,7 +65,7 @@ template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s)
{
if (_s.substr(0, 2) == "0x")
// Hex
return FixedHash<N>(_s.substr(2));
return FixedHash<N>(_s.substr(2 + std::max<unsigned>(40, _s.size() - 2) - 40));
else if (_s.find_first_not_of("0123456789") == std::string::npos)
// Decimal
return (typename FixedHash<N>::Arith)(_s);

2
libdevcrypto/CryptoPP.cpp

@ -199,6 +199,8 @@ bool Secp256k1::verifySecret(Secret const& _s, Public& _p)
void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
{
(void)o_s;
(void)_s;
ECDH<ECP>::Domain d(m_oid);
assert(d.AgreedValueLength() == sizeof(o_s));
byte remote[65] = {0x04};

2
libethereum/Executive.cpp

@ -35,7 +35,7 @@ using namespace dev::eth;
Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
m_s(_s),
m_lastHashes(_s.getLastHashes(_bc)),
m_lastHashes(_s.getLastHashes(_bc, (unsigned)_s.info().number - 1)),
m_depth(_level)
{}

30
libethereum/State.cpp

@ -418,7 +418,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, bo
TransactionReceipts ret;
auto ts = _tq.transactions();
auto lh = getLastHashes(_bc);
auto lh = getLastHashes(_bc, _bc.number());
for (int goodTxs = 1; goodTxs;)
{
@ -498,7 +498,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
GenericTrieDB<MemoryDB> receiptsTrie(&rm);
receiptsTrie.init();
LastHashes lh = getLastHashes(_bc);
LastHashes lh = getLastHashes(_bc, (unsigned)m_previousBlock.number);
// All ok with the block generally. Play back the transactions now...
unsigned i = 0;
@ -527,7 +527,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
cwarn << "Bad receipts state root.";
cwarn << "Block:" << toHex(_block);
cwarn << "Block RLP:" << RLP(_block);
cwarn << "Want: " << receiptsTrie.root() << ", got: " << m_currentBlock.receiptsRoot;
cwarn << "Calculated: " << receiptsTrie.root();
for (unsigned j = 0; j < i; ++j)
{
RLPStream k;
@ -538,6 +538,16 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
cwarn << "Hex: " << toHex(b);
cwarn << TransactionReceipt(&b);
}
cwarn << "Recorded: " << m_currentBlock.receiptsRoot;
auto rs = _bc.receipts(m_currentBlock.hash);
for (unsigned j = 0; j < rs.receipts.size(); ++j)
{
auto b = rs.receipts[j].rlp();
cwarn << j << ": ";
cwarn << "RLP: " << RLP(b);
cwarn << "Hex: " << toHex(b);
cwarn << rs.receipts[j];
}
BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot());
}
@ -1000,19 +1010,29 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
return true;
}
LastHashes State::getLastHashes(BlockChain const& _bc) const
LastHashes State::getLastHashes(BlockChain const& _bc, unsigned _n) const
{
LastHashes ret;
ret.resize(256);
if (c_protocolVersion > 49)
{
ret[0] = _bc.currentHash();
ret[0] = _bc.numberHash(_n);
for (unsigned i = 1; i < 256; ++i)
ret[i] = ret[i - 1] ? _bc.details(ret[i - 1]).parent : h256();
}
return ret;
}
u256 State::execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output, bool _commit)
{
return execute(getLastHashes(_bc, _bc.number()), &_rlp, o_output, _commit);
}
u256 State::execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output, bool _commit)
{
return execute(getLastHashes(_bc, _bc.number()), _rlp, o_output, _commit);
}
// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations.
u256 State::execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output, bool _commit)
{

6
libethereum/State.h

@ -147,12 +147,12 @@ public:
/// Like sync but only operate on _tq, killing the invalid/old ones.
bool cull(TransactionQueue& _tq) const;
LastHashes getLastHashes(BlockChain const& _bc) const;
LastHashes getLastHashes(BlockChain const& _bc, unsigned _n) const;
/// Execute a given transaction.
/// This will append @a _t to the transaction list and change the state accordingly.
u256 execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(getLastHashes(_bc), &_rlp, o_output, _commit); }
u256 execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(getLastHashes(_bc), _rlp, o_output, _commit); }
u256 execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true);
u256 execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true);
u256 execute(LastHashes const& _lh, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(_lh, &_rlp, o_output, _commit); }
u256 execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true);

4
libjsqrc/ethereumjs/dist/ethereum.js

@ -91,8 +91,8 @@ var setupInputTypes = function () {
return value.toString(16);
else if (typeof value === "string" && value.indexOf('0x') === 0)
return value.substr(2);
else if (typeof value === "string")
return web3.toHex(value);
// else if (typeof value === "string")
// return web3.toHex(value);
else
return (+value).toString(16);
};

2
libjsqrc/ethereumjs/dist/ethereum.js.map

File diff suppressed because one or more lines are too long

2
libjsqrc/ethereumjs/dist/ethereum.min.js

File diff suppressed because one or more lines are too long

77
libjsqrc/ethereumjs/example/natspec_contract.html

@ -0,0 +1,77 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/es6-promise/promise.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.AutoProvider());
// solidity source code
var source = "" +
"contract test {\n" +
" /// @notice Will multiplty `a` by 7. \n" +
" function multiply(uint a) returns(uint d) {\n" +
" return a * 7;\n" +
" }\n" +
"}\n";
// contract description, this will be autogenerated somehow
var desc = [{
"name": "multiply",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}];
var contract;
function createExampleContract() {
// hide create button
document.getElementById('create').style.visibility = 'hidden';
document.getElementById('source').innerText = source;
// create contract
web3.eth.transact({code: web3.eth.solidity(source)}).then(function (address) {
contract = web3.contract(address, desc);
document.getElementById('call').style.visibility = 'visible';
});
}
function callExampleContract() {
// this should be generated by ethereum
var param = parseInt(document.getElementById('value').value);
// call the contract
contract.multiply(param).transact().then(function(res) {
document.getElementById('result').innerText = res[0];
});
}
</script>
</head>
<body>
<h1>contract</h1>
<div id="source"></div>
<div id='create'>
<button type="button" onClick="createExampleContract();">create example contract</button>
</div>
<div id='call' style='visibility: hidden;'>
<input type="number" id="value"></input>
<button type="button" onClick="callExampleContract()">Call Contract</button>
</div>
<div id="result"></div>
</body>
</html>

4
libjsqrc/ethereumjs/lib/abi.js

@ -90,8 +90,8 @@ var setupInputTypes = function () {
return value.toString(16);
else if (typeof value === "string" && value.indexOf('0x') === 0)
return value.substr(2);
else if (typeof value === "string")
return web3.toHex(value);
// else if (typeof value === "string")
// return web3.toHex(value);
else
return (+value).toString(16);
};

2
libqwebthree/QWebThree.cpp

@ -140,7 +140,7 @@ void QWebThree::onDataProcessed(QString _json, QString _addInfo)
for (int i = 0; i < resultsArray.size(); i++)
{
QJsonObject elem = resultsArray[i].toObject();
if (elem.contains("result"))
if (elem["result"].isArray() && elem["result"].toArray().size() > 0)
{
QJsonObject res;
res["_event"] = _addInfo;

5
libsolidity/Compiler.cpp

@ -50,10 +50,9 @@ void Compiler::compileContract(ContractDefinition const& _contract, vector<Magic
function->accept(*this);
// Swap the runtime context with the creation-time context
CompilerContext runtimeContext;
swap(m_context, runtimeContext);
swap(m_context, m_runtimeContext);
initializeContext(_contract, _magicGlobals, _contracts);
packIntoContractCreator(_contract, runtimeContext);
packIntoContractCreator(_contract, m_runtimeContext);
}
void Compiler::initializeContext(ContractDefinition const& _contract, vector<MagicVariableDeclaration const*> const& _magicGlobals,

2
libsolidity/Compiler.h

@ -35,6 +35,7 @@ public:
void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals,
std::map<ContractDefinition const*, bytes const*> const& _contracts);
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);}
void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); }
private:
@ -70,6 +71,7 @@ private:
bool const m_optimize;
CompilerContext m_context;
CompilerContext m_runtimeContext;
std::vector<eth::AssemblyItem> m_breakTags; ///< tag to jump to for a "break" statement
std::vector<eth::AssemblyItem> m_continueTags; ///< tag to jump to for a "continue" statement
eth::AssemblyItem m_returnTag; ///< tag to jump to for a "return" statement

13
libsolidity/CompilerStack.cpp

@ -30,6 +30,8 @@
#include <libsolidity/CompilerStack.h>
#include <libsolidity/InterfaceHandler.h>
#include <libdevcrypto/SHA3.h>
using namespace std;
namespace dev
@ -117,6 +119,7 @@ void CompilerStack::compile(bool _optimize)
contractBytecode);
Contract& compiledContract = m_contracts[contract->getName()];
compiledContract.bytecode = compiler->getAssembledBytecode();
compiledContract.runtimeBytecode = compiler->getRuntimeBytecode();
compiledContract.compiler = move(compiler);
contractBytecode[compiledContract.contract] = &compiledContract.bytecode;
}
@ -134,6 +137,16 @@ bytes const& CompilerStack::getBytecode(string const& _contractName) const
return getContract(_contractName).bytecode;
}
bytes const& CompilerStack::getRuntimeBytecode(string const& _contractName) const
{
return getContract(_contractName).runtimeBytecode;
}
dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const
{
return dev::sha3(getRuntimeBytecode(_contractName));
}
void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName) const
{
getContract(_contractName).compiler->streamAssembly(_outStream);

8
libsolidity/CompilerStack.h

@ -28,6 +28,7 @@
#include <memory>
#include <boost/noncopyable.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h>
namespace dev {
namespace solidity {
@ -75,7 +76,13 @@ public:
/// @returns the compiled bytecode
bytes const& compile(std::string const& _sourceCode, bool _optimize = false);
/// @returns the assembled bytecode for a contract.
bytes const& getBytecode(std::string const& _contractName = "") const;
/// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
bytes const& getRuntimeBytecode(std::string const& _contractName = "") const;
/// @returns hash of the runtime bytecode for the contract, i.e. the code that is returned by the constructor.
dev::h256 getContractCodeHash(std::string const& _contractName = "") const;
/// Streams a verbose version of the assembly to @a _outStream.
/// Prerequisite: Successful compilation.
void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "") const;
@ -121,6 +128,7 @@ private:
ContractDefinition const* contract = nullptr;
std::shared_ptr<Compiler> compiler;
bytes bytecode;
bytes runtimeBytecode;
std::shared_ptr<InterfaceHandler> interfaceHandler;
mutable std::unique_ptr<std::string const> interface;
mutable std::unique_ptr<std::string const> solidityInterface;

9
libsolidity/ExpressionCompiler.cpp

@ -326,6 +326,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << u256(32) << u256(0) << eth::logInstruction(logNumber);
break;
}
case Location::BLOCKHASH:
{
arguments[0]->accept(*this);
appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true);
m_context << eth::Instruction::BLOCKHASH;
break;
}
case Location::ECRECOVER:
case Location::SHA256:
case Location::RIPEMD160:
@ -344,7 +351,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
return false;
}
bool ExpressionCompiler::visit(NewExpression const& _newExpression)
bool ExpressionCompiler::visit(NewExpression const&)
{
// code is created for the function call (CREATION) only
return false;

4
libsolidity/InterfaceHandler.cpp

@ -106,7 +106,7 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(ContractDefi
if (!m_notice.empty())
{// since @notice is the only user tag if missing function should not appear
user["notice"] = Json::Value(m_notice);
methods[it.second->getName()] = user;
methods[it.second->getCanonicalSignature()] = user;
}
}
}
@ -162,7 +162,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(ContractDefin
method["return"] = m_return;
if (!method.empty()) // add the function, only if we have any documentation to add
methods[it.second->getName()] = method;
methods[it.second->getCanonicalSignature()] = method;
}
}
doc["methods"] = methods;

4
libsolidity/Token.h

@ -47,6 +47,10 @@
#include <libsolidity/Utils.h>
#include <libsolidity/Exceptions.h>
#if defined(DELETE)
#error The macro "DELETE" from windows.h conflicts with this file. Please change the order of includes.
#endif
namespace dev
{
namespace solidity

4
libsolidity/Types.cpp

@ -693,8 +693,8 @@ MagicType::MagicType(MagicType::Kind _kind):
{
case Kind::BLOCK:
m_members = MemberList({{"coinbase", make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)},
{"timestamp", make_shared<IntegerType >(256)},
{"prevhash", make_shared<IntegerType>(256, IntegerType::Modifier::HASH)},
{"timestamp", make_shared<IntegerType>(256)},
{"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"hash"}, FunctionType::Location::BLOCKHASH)},
{"difficulty", make_shared<IntegerType>(256)},
{"number", make_shared<IntegerType>(256)},
{"gaslimit", make_shared<IntegerType>(256)}});

2
libsolidity/Types.h

@ -354,7 +354,7 @@ public:
SHA3, SUICIDE,
ECRECOVER, SHA256, RIPEMD160,
LOG0, LOG1, LOG2, LOG3, LOG4,
SET_GAS, SET_VALUE,
SET_GAS, SET_VALUE, BLOCKHASH,
BARE };
virtual Category getCategory() const override { return Category::FUNCTION; }

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -84,7 +84,7 @@ static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e)
static Json::Value toJson(dev::eth::LocalisedLogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7.
{
Json::Value res;
Json::Value res(Json::arrayValue);
for (dev::eth::LocalisedLogEntry const& e: _es)
res.append(toJson(e));
return res;

7
mix/AssemblyDebuggerControl.cpp

@ -26,8 +26,8 @@
using namespace dev::mix;
AssemblyDebuggerControl::AssemblyDebuggerControl(dev::mix::AppContext* _context):
Extension(_context, ExtensionDisplayBehavior::ModalDialog)
AssemblyDebuggerControl::AssemblyDebuggerControl(AppContext* _context):
Extension(_context, ExtensionDisplayBehavior::RightView)
{
connect(_context->clientModel(), &ClientModel::showDebuggerWindow, this, &AssemblyDebuggerControl::showDebugger, Qt::QueuedConnection);
}
@ -48,5 +48,6 @@ void AssemblyDebuggerControl::start() const
void AssemblyDebuggerControl::showDebugger()
{
this->addContentOn(this);
QObject* debugPanel = m_view->findChild<QObject*>("debugPanel", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(debugPanel, "update");
}

6
mix/AssemblyDebuggerControl.h

@ -22,13 +22,13 @@
#include <atomic>
#include "Extension.h"
class AppContext;
namespace dev
{
namespace mix
{
class AppContext;
/**
* @brief Extension which display transaction creation or transaction call debugging.
*/
@ -44,7 +44,7 @@ public:
QString contentUrl() const override;
private slots:
/// Update UI with machine states result. Display a modal dialog.
/// Update UI with machine states result. Displayed in the right side tab.
void showDebugger();
};

2
mix/ClientModel.cpp

@ -116,7 +116,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
{
bytes contractCode = compilerRes->bytes();
std::vector<dev::bytes> transactonData;
QFunctionDefinition* f;
QFunctionDefinition* f = nullptr;
ContractCallDataEncoder c;
//encode data for all transactions
for (auto const& t: _sequence)

21
mix/CodeEditorExtensionManager.cpp

@ -25,7 +25,7 @@
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQuickTextDocument>
#include "ConstantCompilationControl.h"
#include "StatusPane.h"
#include "AssemblyDebuggerControl.h"
#include "StateListView.h"
#include "AppContext.h"
@ -56,10 +56,9 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions()
{
std::shared_ptr<ConstantCompilationControl> output = std::make_shared<ConstantCompilationControl>(m_appContext);
std::shared_ptr<StatusPane> output = std::make_shared<StatusPane>(m_appContext);
std::shared_ptr<AssemblyDebuggerControl> debug = std::make_shared<AssemblyDebuggerControl>(m_appContext);
std::shared_ptr<StateListView> stateList = std::make_shared<StateListView>(m_appContext);
QObject::connect(m_appContext->clientModel(), &ClientModel::runFailed, output.get(), &ConstantCompilationControl::displayError);
QObject::connect(m_appContext->codeModel(), &CodeModel::compilationComplete, this, &CodeEditorExtensionManager::applyCodeHighlight);
initExtension(output);
@ -73,10 +72,10 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{
try
{
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab)
_ext->addTabOn(m_tabView);
else if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightTab)
_ext->addTabOn(m_rightTabView);
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightView)
_ext->addTabOn(m_rightView);
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::HeaderView)
_ext->addTabOn(m_headerView);
}
catch (...)
{
@ -93,13 +92,13 @@ void CodeEditorExtensionManager::applyCodeHighlight()
//TODO: reimplement
}
void CodeEditorExtensionManager::setRightTabView(QQuickItem* _tabView)
void CodeEditorExtensionManager::setRightView(QQuickItem* _rightView)
{
m_rightTabView = _tabView;
m_rightView = _rightView;
initExtensions(); //TODO: move this to a proper place
}
void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView)
void CodeEditorExtensionManager::setHeaderView(QQuickItem* _headerView)
{
m_tabView = _tabView;
m_headerView = _headerView;
}

14
mix/CodeEditorExtensionManager.h

@ -26,7 +26,7 @@
#include <QQuickItem>
#include <QTextDocument>
#include <QVector>
#include "ConstantCompilationControl.h"
#include "StatusPane.h"
namespace dev
{
@ -43,8 +43,8 @@ class CodeEditorExtensionManager: public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView)
Q_PROPERTY(QQuickItem* rightTabView MEMBER m_rightTabView WRITE setRightTabView)
Q_PROPERTY(QQuickItem* headerView MEMBER m_headerView WRITE setHeaderView)
Q_PROPERTY(QQuickItem* rightView MEMBER m_rightView WRITE setRightView)
public:
CodeEditorExtensionManager();
@ -54,17 +54,17 @@ public:
/// Initialize extension.
void initExtension(std::shared_ptr<Extension>);
/// Set current tab view
void setTabView(QQuickItem*);
void setHeaderView(QQuickItem*);
/// Set current right tab view.
void setRightTabView(QQuickItem*);
void setRightView(QQuickItem*);
private slots:
void applyCodeHighlight();
private:
QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView;
QQuickItem* m_rightTabView;
QQuickItem* m_headerView;
QQuickItem* m_rightView;
AppContext* m_appContext;
void loadEditor(QQuickItem* _editor);
};

24
mix/CodeModel.cpp

@ -1,18 +1,18 @@
/*
This file is part of cpp-ethereum.
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 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.
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/>.
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 CodeModel.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
@ -168,7 +168,7 @@ void CodeModel::onCompilationComplete(CompilationResult*_newResult)
bool CodeModel::hasContract() const
{
return m_result->contract()->functionsList().size() > 0;
return m_result->successful();
}
void CodeModel::updateFormatting(QTextDocument* _document)

24
mix/CodeModel.h

@ -1,18 +1,18 @@
/*
This file is part of cpp-ethereum.
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 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.
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/>.
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 CodeModel.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
@ -65,6 +65,8 @@ class CompilationResult: public QObject
{
Q_OBJECT
Q_PROPERTY(QContractDefinition* contract READ contract)
Q_PROPERTY(QString compilerMessage READ compilerMessage CONSTANT)
Q_PROPERTY(bool successful READ successful CONSTANT)
public:
/// Empty compilation result constructor

94
mix/ConstantCompilationControl.cpp

@ -1,94 +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 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 "ConstantCompilationControl.h"
#include "QContractDefinition.h"
#include "AppContext.h"
#include "CodeModel.h"
using namespace dev::mix;
ConstantCompilationControl::ConstantCompilationControl(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::Tab)
{
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &ConstantCompilationControl::update);
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &ConstantCompilationControl::update);
}
QString ConstantCompilationControl::contentUrl() const
{
return QStringLiteral("qrc:/qml/BasicContent.qml");
}
QString ConstantCompilationControl::title() const
{
return QApplication::tr("compiler");
}
void ConstantCompilationControl::start() const
{
}
void ConstantCompilationControl::update()
{
auto result = m_ctx->codeModel()->code();
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
if (result->successful())
{
status->setProperty("text", "succeeded");
status->setProperty("color", "green");
content->setProperty("text", result->assemblyCode());
}
else
{
status->setProperty("text", "failure");
status->setProperty("color", "red");
content->setProperty("text", result->compilerMessage());
}
}
void ConstantCompilationControl::resetOutPut()
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
status->setProperty("text", "");
content->setProperty("text", "");
}
void ConstantCompilationControl::displayError(QString const& _error)
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
status->setProperty("text", "failure");
status->setProperty("color", "red");
content->setProperty("text", _error);
}

118
mix/DebuggingStateWrapper.cpp

@ -66,55 +66,134 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
return std::make_tuple(codeStr, QPointer<QQMLMap>(new QQMLMap(codeMapping)));
}
QString DebuggingStateWrapper::gasLeft()
QString DebuggingStateWrapper::gasCost()
{
std::ostringstream ss;
ss << std::dec << (m_state.gas - m_state.gasCost);
ss << std::dec << m_state.gasCost;
return QString::fromStdString(ss.str());
}
QString DebuggingStateWrapper::gasCost()
QString DebuggingStateWrapper::gas()
{
std::ostringstream ss;
ss << std::dec << m_state.gasCost;
ss << std::dec << m_state.gas;
return QString::fromStdString(ss.str());
}
QString DebuggingStateWrapper::gas()
QString DebuggingStateWrapper::newMemSize()
{
std::ostringstream ss;
ss << std::dec << m_state.gas;
ss << std::dec << m_state.newMemSize;
return QString::fromStdString(ss.str());
}
QString DebuggingStateWrapper::debugStack()
QStringList DebuggingStateWrapper::debugStack()
{
QString stack;
QStringList stack;
for (auto i: m_state.stack)
stack.prepend(QString::fromStdString(prettyU256(i)) + "\n");
stack.append(QString::fromStdString(prettyU256(i)));
return stack;
return fillList(stack, "");
}
QString DebuggingStateWrapper::debugStorage()
QStringList DebuggingStateWrapper::debugStorage()
{
std::stringstream s;
QStringList storage;
for (auto const& i: m_state.storage)
{
std::stringstream s;
s << "@" << prettyU256(i.first) << " " << prettyU256(i.second);
storage.append(QString::fromStdString(s.str()));
}
return fillList(storage, "@ -");
}
return QString::fromStdString(s.str());
QVariantList DebuggingStateWrapper::debugMemory()
{
std::vector<std::vector<std::string>> dump = memDumpToList(m_state.memory, 16);
QStringList filled;
filled.append(" ");
filled.append(" ");
filled.append(" ");
return fillList(qVariantDump(dump), QVariant(filled));
}
QString DebuggingStateWrapper::debugMemory()
QVariantList DebuggingStateWrapper::debugCallData()
{
return QString::fromStdString(memDump(m_state.memory, 16, false));
std::vector<std::vector<std::string>> dump = memDumpToList(m_data, 16);
QStringList filled;
filled.append(" ");
filled.append(" ");
filled.append(" ");
return fillList(qVariantDump(dump), QVariant(filled));
}
QString DebuggingStateWrapper::debugCallData()
std::vector<std::vector<std::string>> DebuggingStateWrapper::memDumpToList(bytes const& _bytes, unsigned _width)
{
return QString::fromStdString(memDump(m_data, 16, false));
std::vector<std::vector<std::string>> dump;
for (unsigned i = 0; i < _bytes.size(); i += _width)
{
std::stringstream ret;
std::vector<std::string> dumpLine;
ret << std::hex << std::setw(4) << std::setfill('0') << i << " ";
dumpLine.push_back(ret.str());
ret.str(std::string());
ret.clear();
for (unsigned j = i; j < i + _width; ++j)
if (j < _bytes.size())
if (_bytes[j] >= 32 && _bytes[j] < 127)
ret << (char)_bytes[j];
else
ret << '?';
else
ret << ' ';
dumpLine.push_back(ret.str());
ret.str(std::string());
ret.clear();
for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " ";
dumpLine.push_back(ret.str());
dump.push_back(dumpLine);
}
return dump;
}
QVariantList DebuggingStateWrapper::qVariantDump(std::vector<std::vector<std::string>> const& _dump)
{
QVariantList ret;
for (std::vector<std::string> const& line: _dump)
{
QStringList qLine;
for (std::string const& cell: line)
qLine.push_back(QString::fromStdString(cell));
ret.append(QVariant(qLine));
}
return ret;
}
QStringList DebuggingStateWrapper::fillList(QStringList& _list, QString const& _emptyValue)
{
if (_list.size() < 20)
{
for (int k = _list.size(); k < 20 - _list.size(); k++)
_list.append(_emptyValue);
}
return _list;
}
QVariantList DebuggingStateWrapper::fillList(QVariantList _list, QVariant const& _emptyValue)
{
if (_list.size() < 20)
{
for (int k = _list.size(); k < 20 - _list.size(); k++)
_list.append(_emptyValue);
}
return _list;
}
QStringList DebuggingStateWrapper::levels()
{
QStringList levelsStr;
@ -136,6 +215,11 @@ QString DebuggingStateWrapper::headerInfo()
return QString::fromStdString(ss.str());
}
QString DebuggingStateWrapper::instruction()
{
return QString::fromStdString(dev::eth::instructionInfo(m_state.inst).name);
}
QString DebuggingStateWrapper::endOfDebug()
{
if (m_state.gasCost > m_state.gas)

30
mix/DebuggingStateWrapper.h

@ -83,13 +83,14 @@ class DebuggingStateWrapper: public QObject
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 instruction READ instruction CONSTANT)
Q_PROPERTY(QStringList debugStack READ debugStack CONSTANT)
Q_PROPERTY(QStringList debugStorage READ debugStorage CONSTANT)
Q_PROPERTY(QVariantList debugMemory READ debugMemory CONSTANT)
Q_PROPERTY(QVariantList debugCallData READ debugCallData CONSTANT)
Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT)
Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT)
Q_PROPERTY(QString newMemSize READ newMemSize CONSTANT)
Q_PROPERTY(QStringList levels READ levels CONSTANT)
public:
@ -105,17 +106,21 @@ public:
/// Get gas used.
QString gas();
/// Get stack.
QString debugStack();
QStringList debugStack();
/// Get storage.
QString debugStorage();
QStringList debugStorage();
/// Get memory.
QString debugMemory();
QVariantList debugMemory();
/// Get call data.
QString debugCallData();
QVariantList debugCallData();
/// Get info to be displayed in the header.
QString headerInfo();
/// get end of debug information.
QString endOfDebug();
/// Get the new memory size.
QString newMemSize();
/// Get current instruction
QString instruction();
/// Get all previous steps.
QStringList levels();
/// Get the current processed machine state.
@ -129,6 +134,13 @@ private:
MachineState m_state;
bytes m_code;
bytes m_data;
QStringList fillList(QStringList& _list, QString const& _emptyValue);
QVariantList fillList(QVariantList _list, QVariant const& _emptyValue);
QVariantList qVariantDump(std::vector<std::vector<std::string>> const& _dump);
/// Nicely renders the given bytes to a string, store the content in an array.
/// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line.
std::vector<std::vector<std::string>> memDumpToList(bytes const& _bytes, unsigned _width);
};
}

4
mix/Extension.h

@ -33,8 +33,8 @@ class AppContext;
enum ExtensionDisplayBehavior
{
Tab,
RightTab,
HeaderView,
RightView,
ModalDialog
};

24
mix/StateListView.cpp

@ -1,18 +1,18 @@
/*
This file is part of cpp-ethereum.
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 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.
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/>.
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 StateListView.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
@ -29,7 +29,7 @@
using namespace dev::mix;
StateListView::StateListView(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightTab)
StateListView::StateListView(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightView)
{
}

66
mix/StatusPane.cpp

@ -0,0 +1,66 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file 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 "StatusPane.h"
#include "QContractDefinition.h"
#include "AppContext.h"
#include "CodeModel.h"
using namespace dev::mix;
StatusPane::StatusPane(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::HeaderView)
{
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &StatusPane::update);
_context->appEngine()->rootContext()->setContextProperty("statusPane", this);
}
QString StatusPane::contentUrl() const
{
return QStringLiteral("qrc:/qml/StatusPane.qml");
}
QString StatusPane::title() const
{
return QApplication::tr("compiler");
}
void StatusPane::start() const
{
}
CompilationResult* StatusPane::result() const
{
return m_ctx->codeModel()->code();
}
void StatusPane::update()
{
QObject* ctrl = m_view->findChild<QObject*>("statusPane", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(ctrl, "updateStatus");
}

13
mix/ConstantCompilationControl.h → mix/StatusPane.h

@ -20,6 +20,7 @@
#pragma once
#include "Extension.h"
#include "CodeModel.h"
namespace dev
{
@ -29,23 +30,21 @@ namespace mix
/**
* @brief Extension which display assembly code of the contract being edited.
*/
class ConstantCompilationControl: public Extension
class StatusPane: public Extension
{
Q_OBJECT
Q_PROPERTY(CompilationResult* result READ result CONSTANT)
public:
ConstantCompilationControl(AppContext* _appContext);
~ConstantCompilationControl() {}
StatusPane(AppContext* _appContext);
~StatusPane() {}
void start() const override;
QString title() const override;
QString contentUrl() const override;
private:
void resetOutPut();
CompilationResult* result() const;
public slots:
void update();
void displayError(QString const& _error);
};
}

21
mix/qml.qrc

@ -10,6 +10,27 @@
<file>qml/ProjectList.qml</file>
<file>qml/StateDialog.qml</file>
<file>qml/StateList.qml</file>
<file>qml/img/jumpintoback.png</file>
<file>qml/img/jumpintoforward.png</file>
<file>qml/img/jumpoutback.png</file>
<file>qml/img/jumpoutforward.png</file>
<file>qml/img/jumpoverback.png</file>
<file>qml/img/jumpoverforward.png</file>
<file>qml/StepActionImage.qml</file>
<file>qml/img/jumpintobackdisabled.png</file>
<file>qml/img/jumpintoforwarddisabled.png</file>
<file>qml/img/jumpoutbackdisabled.png</file>
<file>qml/img/jumpoutforwarddisabled.png</file>
<file>qml/img/jumpoverbackdisabled.png</file>
<file>qml/DebugBasicInfo.qml</file>
<file>qml/js/ErrorLocationFormater.js</file>
<file>qml/img/closedtriangleindicator.png</file>
<file>qml/img/opentriangleindicator.png</file>
<file>qml/img/bugiconactive.png</file>
<file>qml/img/bugiconinactive.png</file>
<file>qml/DebugInfoList.qml</file>
<file>qml/ItemDelegateDataDump.qml</file>
<file>qml/StatusPane.qml</file>
<file>qml/TabStyle.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/js/Debugger.js</file>

35
mix/qml/DebugBasicInfo.qml

@ -0,0 +1,35 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
RowLayout {
property string titleStr
width: parent.width
height: parent.height / 4
function update(_value)
{
currentStepValue.text = _value;
}
Rectangle {
width: parent.width / 2
height: parent.height
color: "#e5e5e5"
Text
{
id: title
font.pixelSize: 12
anchors.centerIn: parent
color: "#a2a2a2"
font.family: "Sans Serif"
text: titleStr
}
}
Text
{
font.pixelSize: 13
id: currentStepValue
}
}

83
mix/qml/DebugInfoList.qml

@ -0,0 +1,83 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
ColumnLayout {
property string title
property variant listModel;
property bool collapsible;
property Component itemDelegate
spacing: 0
RowLayout {
height: 25
id: header
Image {
source: "qrc:/qml/img/opentriangleindicator.png"
width: 15
sourceSize.width: 15
id: storageImgArrow
visible: collapsible
}
Text {
anchors.left: storageImgArrow.right
color: "#8b8b8b"
text: title
id: storageListTitle
}
MouseArea
{
enabled: collapsible
anchors.fill: parent
onClicked: {
if (storageContainer.state == "collapsed")
storageContainer.state = "";
else
storageContainer.state = "collapsed";
}
}
}
RowLayout
{
height: parent.height - header.height
clip: true
Rectangle
{
height: parent.height
border.width: 3
border.color: "#deddd9"
Layout.fillWidth: true
states: [
State {
name: "collapsed"
PropertyChanges {
target: storageContainer.parent
height: 0
visible: false
}
PropertyChanges {
target: storageImgArrow
source: "qrc:/qml/img/closedtriangleindicator.png"
}
}
]
id: storageContainer
width: parent.width
ListView {
clip: true;
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 3
anchors.leftMargin: 3
width: parent.width - 3
height: parent.height - 6
id: storageList
model: listModel
delegate: itemDelegate
}
}
}
}

689
mix/qml/Debugger.qml

@ -4,266 +4,505 @@ import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import "js/Debugger.js" as Debugger
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
Rectangle {
id: debugPanel
objectName: "debugPanel"
anchors.fill: parent;
color: "lightgrey"
Component.onCompleted: Debugger.init();
Rectangle {
color: "transparent"
id: headerInfo
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: 60
anchors.top: parent.top
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
}
}
}
}
}
}
Keys.onPressed: {
color: "#ededed"
clip: true
Keys.onPressed:
{
if (event.key === Qt.Key_F10)
Debugger.moveSelection(1);
else if (event.key === Qt.Key_F9)
Debugger.moveSelection(-1);
}
Rectangle {
color: "transparent"
id: stateListContainer
focus: true
anchors.topMargin: 10
anchors.top: headerInfo.bottom
anchors.left: parent.left
height: parent.height - 70
width: parent.width * 0.5
function update()
{
if (statusPane.result.successful)
{
Debugger.init();
debugScrollArea.visible = true;
compilationErrorArea.visible = false;
machineStates.visible = true;
}
else
{
debugScrollArea.visible = false;
compilationErrorArea.visible = true;
machineStates.visible = false;
var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, false);
errorLocation.text = errorInfo.errorLocation;
errorDetail.text = errorInfo.errorDetail;
errorLine.text = errorInfo.errorLine;
}
}
Connections {
target: codeModel
onCompilationComplete: update()
}
ListView {
Rectangle
{
visible: false;
id: compilationErrorArea
width: parent.width - 20
height: 500
color: "#ededed"
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: 10
ColumnLayout
{
width: parent.width
anchors.top: parent.top
height: parent.height * 0.60
width: 200
anchors.horizontalCenter: parent.horizontalCenter
id: statesList
model: humanReadableExecutionCode
delegate: renderDelegate
highlight: highlightBar
highlightFollowsCurrentItem: true
}
spacing: 25
RowLayout
{
height: 100
ColumnLayout
{
Text {
color: "red"
id: errorLocation
}
Text {
color: "#4a4a4a"
id: errorDetail
}
}
}
Component {
id: highlightBar
Rectangle {
height: statesList.currentItem.height
width: statesList.currentItem.width
border.color: "orange"
border.width: 1
Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
Rectangle
{
width: parent.width - 6
height: 2
color: "#d0d0d0"
}
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
Text {
anchors.centerIn: parent
text: line
font.pointSize: 9
RowLayout
{
Text
{
color: "#4a4a4a"
id: errorLine
}
}
}
}
Rectangle {
id: callStackPanel
anchors.top: statesList.bottom
height: parent.height * 0.35
width: parent.width
Flickable {
property int firstColumnWidth: 170
property int secondColumnWidth: 250
id: debugScrollArea
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
contentHeight: machineStates.height + 300
contentWidth: machineStates.width
GridLayout
{
property int sideMargin: 10
id: machineStates
anchors.top: parent.top
anchors.topMargin: 15
color: "transparent"
Label {
id: callStackLabel
anchors.bottomMargin: 10
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
font.letterSpacing: 2
width: parent.width
height: 15
text: qsTr("callstack")
}
anchors.left: parent.left;
anchors.leftMargin: machineStates.sideMargin
anchors.right: parent.right;
anchors.rightMargin: machineStates.sideMargin
flow: GridLayout.TopToBottom
rowSpacing: 15
RowLayout {
// step button + slider
spacing: machineStates.sideMargin
height: 27
width: debugPanel.width
Rectangle
{
height: parent.height
color: "transparent"
width: debugScrollArea.firstColumnWidth
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
spacing: 3
StepActionImage
{
id: jumpOutBackAction;
enabledStateImg: "qrc:/qml/img/jumpoutback.png"
disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png"
onClicked: Debugger.stepOutBack()
width: 25
height: 27
}
ListView {
height: parent.height - 15
width: 200
anchors.top: callStackLabel.bottom
anchors.horizontalCenter: parent.horizontalCenter
id: levelList
delegate: Component {
Item {
Text {
font.family: "Verdana"
font.pointSize: 8
text: modelData
StepActionImage
{
id: jumpIntoBackAction
enabledStateImg: "qrc:/qml/img/jumpintoback.png"
disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png"
onClicked: Debugger.stepIntoBack()
width: 25
height: 27
}
StepActionImage
{
id: jumpOverBackAction
enabledStateImg: "qrc:/qml/img/jumpoverback.png"
disableStateImg: "qrc:/qml/img/jumpoverbackdisabled.png"
onClicked: Debugger.stepOverBack()
width: 25
height: 27
}
StepActionImage
{
id: jumpOverForwardAction
enabledStateImg: "qrc:/qml/img/jumpoverforward.png"
disableStateImg: "qrc:/qml/img/jumpoverforwarddisabled.png"
onClicked: Debugger.stepOverForward()
width: 25
height: 27
}
StepActionImage
{
id: jumpIntoForwardAction
enabledStateImg: "qrc:/qml/img/jumpintoforward.png"
disableStateImg: "qrc:/qml/img/jumpintoforwarddisabled.png"
onClicked: Debugger.stepIntoForward()
width: 25
height: 27
}
StepActionImage
{
id: jumpOutForwardAction
enabledStateImg: "qrc:/qml/img/jumpoutforward.png"
disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png"
onClicked: Debugger.stepOutForward()
width: 25
height: 27
}
}
}
Rectangle {
color: "transparent"
width: debugScrollArea.secondColumnWidth
height: parent.height
Slider {
id: statesSlider
anchors.fill: parent
tickmarksEnabled: true
stepSize: 1.0
onValueChanged: Debugger.jumpTo(value);
style: SliderStyle {
groove: Rectangle {
implicitHeight: 3
color: "#7da4cd"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 10
implicitHeight: 10
radius: 12
}
}
}
}
}
}
}
Rectangle {
color: "transparent"
anchors.topMargin: 5
anchors.bottomMargin: 10
anchors.rightMargin: 10
height: parent.height - 30
width: parent.width * 0.5
anchors.right: parent.right
anchors.top: headerInfo.bottom
anchors.bottom: parent.bottom
RowLayout {
// Assembly code
width: debugPanel.width
height: 405
spacing: machineStates.sideMargin
Rectangle {
id: debugStack
anchors.top: parent.top
width: parent.width
height: parent.height * 0.25
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug stack")
}
TextArea {
anchors.bottom: parent.bottom
width: parent.width
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id: debugStackTxt
readOnly: true;
Rectangle
{
width: debugScrollArea.firstColumnWidth
height: parent.height
border.width: 3
border.color: "#deddd9"
color: "white"
anchors.top: parent.top
ListView {
anchors.fill: parent
anchors.leftMargin: 3
anchors.rightMargin: 3
anchors.topMargin: 3
anchors.bottomMargin: 3
clip: true
id: statesList
delegate: renderDelegate
highlight: highlightBar
highlightFollowsCurrentItem: true
}
Component {
id: highlightBar
Rectangle {
radius: 4
height: statesList.currentItem.height
width: statesList.currentItem.width;
color: "#4A90E2"
Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
}
}
Component {
id: renderDelegate
RowLayout {
id: wrapperItem
height: 20
width: parent.width
spacing: 5
Text {
anchors.left: parent.left
anchors.leftMargin: 10
width: 15
color: "#b2b3ae"
text: line.split(' ')[0]
font.pointSize: 9
id: id
wrapMode: Text.NoWrap
}
Text {
wrapMode: Text.NoWrap
color: parent.ListView.isCurrentItem ? "white" : "black"
text: line.replace(line.split(' ')[0], '')
anchors.left: id.right
font.pointSize: 9
}
}
}
}
ColumnLayout {
width: debugScrollArea.secondColumnWidth
height: parent.height
Rectangle {
// Info
width: parent.width
id: basicInfoColumn
height: 125
color: "transparent"
ColumnLayout {
spacing: 0
width: parent.width
height: parent.height
DebugBasicInfo {
id: currentStep
titleStr: qsTr("Current step")
}
DebugBasicInfo {
id: mem
titleStr: qsTr("Adding memory")
}
DebugBasicInfo {
id: stepCost
titleStr: qsTr("Step cost")
}
DebugBasicInfo {
id: gasSpent
titleStr: qsTr("Total gas spent")
}
}
}
Rectangle {
// Stack
height: 275
width: parent.width
color: "transparent"
DebugInfoList
{
id: stack
width: parent.width
height: parent.height
collapsible: false
title : qsTr("Stack")
itemDelegate: Item {
id: renderedItem
height: 27
width: parent.width
RowLayout
{
anchors.fill: parent
Rectangle
{
id: indexColumn
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.preferredWidth: 30
Layout.maximumWidth: 30
Layout.minimumHeight: parent.height
Text {
anchors.centerIn: parent
anchors.leftMargin: 5
color: "#8b8b8b"
text: model.index;
font.pointSize: 9
}
}
Rectangle
{
anchors.left: indexColumn.right
Layout.fillWidth: true
Layout.minimumWidth: 15
Layout.preferredWidth: 15
Layout.maximumWidth: 60
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData
font.pointSize: 9
}
}
}
Rectangle {
id: separator
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
}
}
}
}
}
Rectangle {
id: debugMemory
anchors.top: debugStack.bottom
width: parent.width
height: parent.height * 0.25
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug memory")
Rectangle {
width: debugPanel.width - 2 * machineStates.sideMargin
height: 2;
color: "#e3e3e3"
radius: 3
}
TextArea {
anchors.bottom: parent.bottom
width: parent.width
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id: debugMemoryTxt
readOnly: true;
DebugInfoList
{
id: storage
width: debugPanel.width - 2 * machineStates.sideMargin
height: 223
collapsible: true
title : qsTr("Storage")
itemDelegate:
Item {
height: 27
width: parent.width;
RowLayout
{
id: row
width: parent.width
height: 26
Rectangle
{
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
color: "#8b8b8b"
text: modelData.split(' ')[0].substring(0, 10);
font.pointSize: 9
}
}
Rectangle
{
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.leftMargin: 5
width: parent.width - 5
wrapMode: Text.Wrap
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData.split(' ')[1].substring(0, 10);
font.pointSize: 9
}
}
}
Rectangle {
anchors.top: row.bottom
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
}
}
Rectangle {
id: debugStorage
anchors.top: debugMemory.bottom
width: parent.width
height: parent.height * 0.25
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug storage")
Rectangle {
width: debugPanel.width - 2 * machineStates.sideMargin
height: 2;
color: "#e3e3e3"
radius: 3
}
TextArea {
anchors.bottom: parent.bottom
width: parent.width
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id: debugStorageTxt
readOnly: true;
DebugInfoList {
id: memoryDump
width: debugPanel.width - 2 * machineStates.sideMargin
height: 223
collapsible: true
title: qsTr("Memory Dump")
itemDelegate:
Item {
height: 29
width: parent.width - 3;
ItemDelegateDataDump {}
}
}
}
Rectangle {
id: debugCallData
anchors.top: debugStorage.bottom
width: parent.width
height: parent.height * 0.25
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug calldata")
Rectangle {
width: debugPanel.width - 2 * machineStates.sideMargin
height: 2;
color: "#e3e3e3"
radius: 3
}
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;
DebugInfoList {
id: callDataDump
width: debugPanel.width - 2 * machineStates.sideMargin
height: 223
collapsible: true
title: qsTr("Call data")
itemDelegate:
Item {
height: 29
width: parent.width - 3;
ItemDelegateDataDump {}
}
}
}
}

71
mix/qml/ItemDelegateDataDump.qml

@ -0,0 +1,71 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
Rectangle {
anchors.fill: parent
RowLayout
{
id: row;
anchors.fill: parent
spacing: 2
Rectangle
{
id: firstCol;
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 35
Layout.preferredWidth: 35
Layout.maximumWidth: 35
Layout.minimumHeight: parent.height
Text {
anchors.centerIn: parent
anchors.leftMargin: 5
color: "#8b8b8b"
text: modelData[0]
font.pointSize: 9;
}
}
Rectangle
{
anchors.left: firstCol.right
Layout.fillWidth: true
Layout.minimumWidth: 90
Layout.preferredWidth: 90
Layout.maximumWidth: 90
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.leftMargin: 7
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData[1]
font.pointSize: 9
}
}
Rectangle
{
Layout.fillWidth: true
Layout.minimumWidth: 50
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: "#ededed"
font.bold: true
text: modelData[2]
font.pointSize: 10
}
}
}
Rectangle {
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}

196
mix/qml/MainContent.qml

@ -5,6 +5,7 @@ import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0
Rectangle {
objectName: "mainContent"
signal keyPressed(variant event)
focus: true
@ -14,59 +15,152 @@ Rectangle {
root.keyPressed(event.key);
}
anchors.fill: parent
height: parent.height
width: parent.width;
id:root
SplitView {
orientation: Qt.Horizontal
anchors.fill: parent
ProjectList {
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 200
id: root
function toggleRightView()
{
if (!rightView.visible)
rightView.show();
else
rightView.hide();
}
function ensureRightView()
{
if (!rightView.visible)
rightView.show();
}
function hideRightView()
{
if (rightView.visible)
rightView.hide();
}
CodeEditorExtensionManager {
headerView: headerPaneTabs;
rightView: rightPaneTabs;
}
GridLayout
{
anchors.fill: parent
rows: 2
flow: GridLayout.TopToBottom
columnSpacing: 0
rowSpacing: 0
Rectangle {
width: parent.width
height: 50
Layout.row: 0
Layout.fillWidth: true
Layout.preferredHeight: 50
id: headerView
Rectangle
{
gradient: Gradient {
GradientStop { position: 0.0; color: "#f1f1f1" }
GradientStop { position: 1.0; color: "#d9d7da" }
}
id: headerPaneContainer
anchors.fill: parent
TabView {
id: headerPaneTabs
tabsVisible: false
antialiasing: true
anchors.fill: parent
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {}
frame: Rectangle { color: "transparent" }
}
}
}
}
SplitView {
//anchors.fill: parent
width: parent.width * 0.6
orientation: Qt.Vertical
CodeEditorView {
height: parent.height * 0.7
anchors.top: parent.top
width: parent.width
SplitView {
resizing: false
Layout.row: 1
orientation: Qt.Horizontal;
Layout.fillWidth: true
Layout.preferredHeight: root.height - headerView.height;
ProjectList {
id: projectList
width: 200
height: parent.height
Layout.minimumWidth: 200
}
Rectangle {
id: contentView
width: parent.width - projectList.width
height: parent.height
CodeEditorView {
height: parent.height
anchors.top: parent.top
width: parent.width
}
}
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
}
}
Rectangle {
visible: false;
id: rightView;
Keys.onEscapePressed:
{
hide();
}
function show() {
visible = true;
contentView.width = parent.width - projectList.width - rightView.width;
}
function hide() {
visible = false;
contentView.width = parent.width - projectList.width;
}
height: parent.height;
width: 450
Layout.minimumWidth: 450
Rectangle {
anchors.fill: parent;
id: rightPaneView
TabView {
id: rightPaneTabs
tabsVisible: true
antialiasing: true
anchors.fill: parent
style: TabViewStyle {
frameOverlap: 1
tabBar:
Rectangle {
color: "#ededed"
id: background
}
tab: Rectangle {
color: "#ededed"
implicitWidth: 80
implicitHeight: 20
radius: 2
Text {
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "#7da4cd" : "#202020"
}
}
frame: Rectangle {
}
}
}
}
}
}
}
}

7
mix/qml/StateList.qml

@ -6,7 +6,7 @@ import QtQuick.Layouts 1.1
import org.ethereum.qml.ProjectModel 1.0
Rectangle {
color: "transparent"
color: "#ededed"
id: stateListContainer
focus: true
anchors.topMargin: 10
@ -123,7 +123,10 @@ Rectangle {
ToolButton {
text: qsTr("Run");
Layout.fillHeight: true
onClicked: stateListModel.runState(index);
onClicked:
{
stateListModel.runState(index)
}
}
}
}

116
mix/qml/StatusPane.qml

@ -0,0 +1,116 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
Rectangle {
id: statusHeader
objectName: "statusPane"
function updateStatus()
{
if (statusPane.result.successful)
{
status.state = "";
status.text = qsTr("Compile without errors.");
logslink.visible = false;
}
else
{
status.state = "error";
var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, true);
status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail;
logslink.visible = true;
}
debugRunActionIcon.enabled = statusPane.result.successful;
}
color: "transparent"
anchors.fill: parent
Rectangle {
id: statusContainer
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
radius: 3
width: 500
height: 30
color: "#fcfbfc"
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Text {
font.pointSize: 10
height: 9
font.family: "sans serif"
objectName: "status"
id: status
states:[
State {
name: "error"
PropertyChanges {
target: status
color: "red"
}
PropertyChanges {
target: statusContainer
color: "#fffcd5"
}
}
]
}
Text {
visible: false
font.pointSize: 9
height: 9
text: qsTr("See log.")
font.family: "Monospace"
objectName: "status"
id: logslink
color: "#8c8a74"
MouseArea {
anchors.fill: parent
onClicked: {
mainContent.ensureRightView();
}
}
}
}
}
Rectangle
{
color: "transparent"
width: 100
height: parent.height
anchors.top: statusHeader.top
anchors.right: statusHeader.right
RowLayout
{
anchors.fill: parent
Rectangle {
color: "transparent"
anchors.fill: parent
Button
{
anchors.right: parent.right
anchors.rightMargin: 7
anchors.verticalCenter: parent.verticalCenter
id: debugImg
iconSource: "qrc:/qml/img/bugiconinactive.png"
action: debugRunActionIcon
}
Action {
id: debugRunActionIcon
onTriggered: {
mainContent.ensureRightView();
clientModel.debugDeployment();
}
enabled: false
}
}
}
}
}

39
mix/qml/StepActionImage.qml

@ -0,0 +1,39 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
Rectangle {
id: buttonActionContainer
property string disableStateImg
property string enabledStateImg
signal clicked
function enabled(state)
{
buttonAction.enabled = state;
if (state)
debugImg.iconSource = enabledStateImg;
else
debugImg.iconSource = disableStateImg;
}
color: "transparent"
Button
{
anchors.fill: parent
id: debugImg
iconSource: enabledStateImg
action: buttonAction
width: buttonActionContainer.width - 3
height: buttonActionContainer.height
}
Action {
id: buttonAction
onTriggered: {
buttonActionContainer.clicked();
}
}
}

BIN
mix/qml/img/bugiconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
mix/qml/img/bugiconinactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
mix/qml/img/closedtriangleindicator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

BIN
mix/qml/img/jumpintoback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

BIN
mix/qml/img/jumpintobackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

BIN
mix/qml/img/jumpintoforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

BIN
mix/qml/img/jumpintoforwarddisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

BIN
mix/qml/img/jumpoutback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

BIN
mix/qml/img/jumpoutbackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

BIN
mix/qml/img/jumpoutforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

BIN
mix/qml/img/jumpoutforwarddisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

BIN
mix/qml/img/jumpoverback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

BIN
mix/qml/img/jumpoverbackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

BIN
mix/qml/img/jumpoverforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

BIN
mix/qml/img/opentriangleindicator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

147
mix/qml/js/Debugger.js

@ -4,11 +4,22 @@
//statesList => ListView
var currentSelectedState = null;
var jumpStartingPoint = null;
function init()
{
if (debugStates === undefined)
return;
statesSlider.maximumValue = debugStates.length - 1;
statesSlider.value = 0;
statesList.model = humanReadableExecutionCode;
currentSelectedState = 0;
select(currentSelectedState);
displayReturnValue();
jumpOutBackAction.enabled(false);
jumpIntoBackAction.enabled(false);
jumpIntoForwardAction.enabled(false);
jumpOutForwardAction.enabled(false);
}
function moveSelection(incr)
@ -16,25 +27,34 @@ function moveSelection(incr)
if (currentSelectedState + incr >= 0)
{
if (currentSelectedState + incr < debugStates.length)
{
select(currentSelectedState + incr);
}
else
{
endOfDebug();
}
statesSlider.value = currentSelectedState;
}
}
function select(stateIndex)
{
var codeLine = codeStr(stateIndex);
var state = debugStates[stateIndex];
var codeStr = bytesCodeMapping.getValue(state.curPC);
highlightSelection(codeStr);
highlightSelection(codeLine);
currentSelectedState = stateIndex;
completeCtxInformation(state);
levelList.model = state.levels;
levelList.update();
if (state.instruction === "JUMP")
jumpIntoForwardAction.enabled(true);
else
jumpIntoForwardAction.enabled(false);
if (state.instruction === "JUMPDEST")
jumpIntoBackAction.enabled(true);
else
jumpIntoBackAction.enabled(false);
}
function codeStr(stateIndex)
{
var state = debugStates[stateIndex];
return bytesCodeMapping.getValue(state.curPC);
}
function highlightSelection(index)
@ -44,21 +64,15 @@ function highlightSelection(index)
function completeCtxInformation(state)
{
debugStackTxt.text = state.debugStack;
debugStorageTxt.text = state.debugStorage;
debugMemoryTxt.text = state.debugMemory;
debugCallDataTxt.text = state.debugCallData;
headerInfoLabel.text = state.headerInfo
}
currentStep.update(state.step);
mem.update(state.newMemSize + " " + qsTr("words"));
stepCost.update(state.gasCost);
gasSpent.update(debugStates[0].gas - state.gas);
function endOfDebug()
{
var state = debugStates[debugStates.length - 1];
debugStorageTxt.text = "";
debugCallDataTxt.text = "";
debugStackTxt.text = "";
debugMemoryTxt.text = state.endOfDebug;
headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft;
stack.listModel = state.debugStack;
storage.listModel = state.debugStorage;
memoryDump.listModel = state.debugMemory;
callDataDump.listModel = state.debugCallData;
}
function displayReturnValue()
@ -66,3 +80,86 @@ function displayReturnValue()
headerReturnList.model = contractCallReturnParameters;
headerReturnList.update();
}
function stepOutBack()
{
if (jumpStartingPoint != null)
{
select(jumpStartingPoint);
jumpStartingPoint = null;
jumpOutBackAction.enabled(false);
jumpOutForwardAction.enabled(false);
}
}
function stepIntoBack()
{
moveSelection(-1);
}
function stepOverBack()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMPDEST")
{
for (var k = currentSelectedState; k > 0; k--)
{
var line = bytesCodeMapping.getValue(debugStates[k].curPC);
if (line === statesList.currentIndex - 2)
{
select(k);
break;
}
}
}
else
moveSelection(-1);
}
function stepOverForward()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMP")
{
for (var k = currentSelectedState; k < debugStates.length; k++)
{
var line = bytesCodeMapping.getValue(debugStates[k].curPC);
if (line === statesList.currentIndex + 2)
{
select(k);
break;
}
}
}
else
moveSelection(1);
}
function stepIntoForward()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMP")
{
jumpStartingPoint = currentSelectedState;
moveSelection(1);
jumpOutBackAction.enabled(true);
jumpOutForwardAction.enabled(true);
}
}
function stepOutForward()
{
if (jumpStartingPoint != null)
{
stepOutBack();
stepOverForward();
jumpOutBackAction.enabled(false);
jumpOutForwardAction.enabled(false);
}
}
function jumpTo(value)
{
currentSelectedState = value;
select(currentSelectedState);
}

27
mix/qml/js/ErrorLocationFormater.js

@ -0,0 +1,27 @@
function formatLocation(raw, shortMessage)
{
var splitted = raw.split(':');
if (!shortMessage)
return qsTr("Error in line ") + splitted[1] + ", " + qsTr("character ") + splitted[2];
else
return "L" + splitted[1] + "," + "C" + splitted[2];
}
function extractErrorInfo(raw, shortMessage)
{
var _return = {};
var detail = raw.split('\n')[0];
var reg = detail.match(/:\d+:\d+:/g);
if (reg !== null)
{
_return.errorLocation = ErrorLocationFormater.formatLocation(reg[0], shortMessage);
_return.errorDetail = detail.replace(reg[0], "");
}
else
{
_return.errorLocation = "";
_return.errorDetail = detail;
}
_return.errorLine = raw.split('\n')[1];
return _return;
}

19
mix/qml/main.qml

@ -38,13 +38,20 @@ ApplicationWindow {
MenuItem { action: debugRunAction }
MenuItem { action: debugResetStateAction }
}
Menu {
title: qsTr("Windows")
MenuItem { action: showHideRightPanel }
}
}
Component.onCompleted: {
setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2);
}
MainContent {
id: mainContent;
anchors.fill: parent
}
ModalDialog {
@ -68,8 +75,11 @@ ApplicationWindow {
id: debugRunAction
text: "&Run"
shortcut: "F5"
onTriggered: {
mainContent.ensureRightView();
clientModel.debugDeployment();
}
enabled: codeModel.hasContract && !clientModel.running;
onTriggered: clientModel.debugDeployment();
}
Action {
@ -79,6 +89,13 @@ ApplicationWindow {
onTriggered: clientModel.resetState();
}
Action {
id: showHideRightPanel
text: "Show/Hide right view"
shortcut: "F7"
onTriggered: mainContent.toggleRightView();
}
Action {
id: createProjectAction
text: qsTr("&New project")

4
standard.js

@ -1,10 +1,13 @@
var compile = function(name) { return web3.eth.solidity(env.contents("../../dapp-bin/" + name + "/" + name + ".sol")); };
var create = function(code) { return web3.eth.transact({ 'code': code }); };
var createVal = function(code, val) { return web3.eth.transact(val ? { 'code': code, 'value': val } : { 'code': code }); };
var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); };
var initService = function(name, dep) { return dep.then(function(){ return compile(name).then(create); }); };
var initServiceVal = function(name, dep, val) { return dep.then(function(){ return compile(name).then(function(c) { createVal(c, val); }); }); };
var addrConfig = compile("config").then(create);
var addrNameReg = initService("namereg", addrConfig);
var addrGavsino = initServiceVal("gavmble", addrNameReg, "1000000000000000000");
var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"string32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"string32"}]},{"constant":false,"inputs":[{"name":"name","type":"string32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}];
var regName = function(account, name) { return web3.contract(addrNameReg, abiNameReg).register(name).transact({'from': account, 'gas': 10000}); };
@ -26,6 +29,7 @@ addrConfig.then(function() {
regName(accounts[1], 'Gav Would');
});
regName(accounts[0], 'Gav');
// TODO: once we have the exchange.
// approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); });
// funded.then(function(){ approve(accounts[1], exchange); });

16
test/SolidityEndToEndTest.cpp

@ -28,10 +28,6 @@
#include <libdevcrypto/SHA3.h>
#include <test/solidityExecutionFramework.h>
#ifdef _MSC_VER
#pragma warning(disable: 4307) //integral constant overflow for high_bits_cleaning
#endif
using namespace std;
namespace dev
@ -386,7 +382,8 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning)
{
char const* sourceCode = "contract test {\n"
" function run() returns(uint256 y) {\n"
" uint32 x = uint32(0xffffffff) + 10;\n"
" uint32 t = uint32(0xffffffff);\n"
" uint32 x = t + 10;\n"
" if (x >= 0xffffffff) return 0;\n"
" return x;"
" }\n"
@ -394,7 +391,8 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning)
compileAndRun(sourceCode);
auto high_bits_cleaning_cpp = []() -> u256
{
uint32_t x = uint32_t(0xffffffff) + 10;
uint32_t t = uint32_t(0xffffffff);
uint32_t x = t + 10;
if (x >= 0xffffffff)
return 0;
return x;
@ -426,14 +424,16 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types)
{
char const* sourceCode = "contract test {\n"
" function run() returns(uint256 y) {\n"
" uint32 x = uint32(0xffffff) * 0xffffff;\n"
" uint32 t = uint32(0xffffff);\n"
" uint32 x = t * 0xffffff;\n"
" return x / 0x100;"
" }\n"
"}\n";
compileAndRun(sourceCode);
auto small_unsigned_types_cpp = []() -> u256
{
uint32_t x = uint32_t(0xffffff) * 0xffffff;
uint32_t t = uint32_t(0xffffff);
uint32_t x = t * 0xffffff;
return x / 0x100;
};
testSolidityAgainstCpp("run()", small_unsigned_types_cpp);

42
test/SolidityNatspecJSON.cpp

@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(user_basic_test)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \"notice\": \"Multiplies `a` by 7\"}"
" \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}"
"}}";
checkNatspec(sourceCode, natspec, true);
@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
char const* devNatspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7\"\n"
" }\n"
" }\n"
@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
char const* userNatspec = "{"
"\"methods\":{"
" \"mul\":{ \"notice\": \"Multiplies `a` by 7\"}"
" \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}"
"}}";
checkNatspec(sourceCode, devNatspec, false);
@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment)
char const* natspec = "{"
"\"methods\":{"
" \"mul_and_add\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}"
" \"mul_and_add(uint256,uint256)\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}"
"}}";
checkNatspec(sourceCode, natspec, true);
@ -157,9 +157,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions)
char const* natspec = "{"
"\"methods\":{"
" \"mul_and_add\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"},"
" \"divide\":{ \"notice\": \"Divides `input` by `div`\"},"
" \"sub\":{ \"notice\": \"Subtracts 3 from `input`\"}"
" \"mul_and_add(uint256,uint256)\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"},"
" \"divide(uint256,uint256)\":{ \"notice\": \"Divides `input` by `div`\"},"
" \"sub(int256)\":{ \"notice\": \"Subtracts 3 from `input`\"}"
"}}";
checkNatspec(sourceCode, natspec, true);
@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \" Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter\",\n"
@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter\",\n"
@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n"
@ -289,21 +289,21 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter\",\n"
" \"second\": \"Documentation for the second parameter\"\n"
" }\n"
" },\n"
" \"divide\":{ \n"
" \"divide(uint256,uint256)\":{ \n"
" \"details\": \"Divides 2 numbers\",\n"
" \"params\": {\n"
" \"input\": \"Documentation for the input parameter\",\n"
" \"div\": \"Documentation for the div parameter\"\n"
" }\n"
" },\n"
" \"sub\":{ \n"
" \"sub(int256)\":{ \n"
" \"details\": \"Subtracts 3 from `input`\",\n"
" \"params\": {\n"
" \"input\": \"Documentation for the input parameter\"\n"
@ -327,7 +327,7 @@ BOOST_AUTO_TEST_CASE(dev_return)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n"
@ -353,7 +353,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n"
@ -381,7 +381,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n"
@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment)
char const* natspec = "{"
"\"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Multiplies a number by 7 and adds second parameter\",\n"
" \"params\": {\n"
" \"a\": \"Documentation for the first parameter starts here. Since it's a really complicated parameter we need 2 lines\",\n"
@ -432,7 +432,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc)
char const* natspec = "{"
" \"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Mul function\"\n"
" }\n"
" }\n"
@ -454,7 +454,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc)
" \"author\": \"Lefteris\","
" \"title\": \"Just a test contract\","
" \"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Mul function\"\n"
" }\n"
" }\n"
@ -477,7 +477,7 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function)
" \"author\": \"Lefteris\","
" \"title\": \"Just a test contract\","
" \"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Mul function\",\n"
" \"author\": \"John Doe\",\n"
" }\n"
@ -501,7 +501,7 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error)
" \"author\": \"Lefteris\","
" \"title\": \"Just a test contract\","
" \"methods\":{"
" \"mul\":{ \n"
" \"mul(uint256,uint256)\":{ \n"
" \"details\": \"Mul function\"\n"
" }\n"
" }\n"

17
test/vm.cpp

@ -508,23 +508,28 @@ BOOST_AUTO_TEST_CASE(vmLogTest)
dev::test::executeTests("vmLogTest", "/VMTests", dev::test::doVMTests);
}
BOOST_AUTO_TEST_CASE(vmPerformanceTest)
BOOST_AUTO_TEST_CASE(vmSystemOperationsTest)
{
dev::test::executeTests("vmSystemOperationsTest", "/VMTests", dev::test::doVMTests);
}
BOOST_AUTO_TEST_CASE(vmInputLimitsTest1)
{
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
{
string arg = boost::unit_test::framework::master_test_suite().argv[i];
if (arg == "--performance")
dev::test::executeTests("vmPerformanceTest", "/VMTests", dev::test::doVMTests);
if (arg == "--inputlimits")
dev::test::executeTests("vmInputLimitsTest1", "/VMTests", dev::test::doVMTests);
}
}
BOOST_AUTO_TEST_CASE(vmArithPerformanceTest)
BOOST_AUTO_TEST_CASE(vmInputLimitsTest2)
{
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
{
string arg = boost::unit_test::framework::master_test_suite().argv[i];
if (arg == "--performance")
dev::test::executeTests("vmArithPerformanceTest", "/VMTests", dev::test::doVMTests);
if (arg == "--inputlimits")
dev::test::executeTests("vmInputLimitsTest2", "/VMTests", dev::test::doVMTests);
}
}

36
test/vmSystemOperationsTestFiller.json

@ -12,7 +12,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ (MSTORE 0 0x601080600c6000396000f200600035560f6009590060203560003557) [[ 0 ]] (CREATE 23 4 28) }",
"code" : "{ (MSTORE 0 0x601080600c6000396000f3006000355415600957005b60203560003555) [[ 0 ]] (CREATE 23 3 29) }",
"storage": {}
}
},
@ -40,7 +40,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100",
"nonce" : 0,
"code" : "{ (MSTORE 0 0x601080600c6000396000f200600035560f6009590060203560003557) [[ 0 ]] (CREATE 230 4 28) }",
"code" : "{ (MSTORE 0 0x601080600c6000396000f3006000355415600957005b60203560003555) [[ 0 ]] (CREATE 230 3 29) }",
"storage": {}
}
},
@ -68,7 +68,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100",
"nonce" : 0,
"code" : "{ (MSTORE 0 0x601080600c6000396000f200600035560f6009590060203560003557) [[ 0 ]] (CREATE 23 0xfffffffffff 28) }",
"code" : "{ (MSTORE 0 0x601080600c6000396000f3006000355415600957005b60203560003555) [[ 0 ]] (CREATE 23 0xfffffffffff 29) }",
"storage": {}
}
},
@ -96,7 +96,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100",
"nonce" : 0,
"code" : "{ (MSTORE 0 0x601080600c6000396000f200600035560f6009590060203560003557) [[ 0 ]] (CREATE 23 4 0xffffffff) }",
"code" : "{ (MSTORE 0 0x601080600c6000396000f3006000355415600957005b60203560003555) [[ 0 ]] (CREATE 23 3 0xffffffff) }",
"storage": {}
}
},
@ -129,7 +129,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -340,7 +340,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -376,7 +376,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -412,7 +412,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -448,7 +448,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -485,7 +485,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -521,7 +521,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -675,7 +675,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -711,7 +711,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -747,7 +747,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -873,7 +873,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -909,7 +909,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -945,7 +945,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"nonce" : "0",
"storage" : {
}
@ -976,7 +976,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x600035560f600a59005d60203560003557",
"code" : "0x6000355415600957005b60203560003555",
"storage": {}
}
},

Loading…
Cancel
Save