Browse Source

Merge remote-tracking branch 'upstream/develop' into evmjit

Conflicts:
	evmjit/libevmjit/Arith256.cpp
cl-refactor
Paweł Bylica 10 years ago
parent
commit
2d7b3de162
  1. 1
      CMakeLists.txt
  2. 43
      CodingStandards.txt
  3. 8
      alethzero/CMakeLists.txt
  4. 59
      alethzero/Context.cpp
  5. 68
      alethzero/Context.h
  6. 380
      alethzero/Debugger.cpp
  7. 103
      alethzero/Debugger.h
  8. 300
      alethzero/Debugger.ui
  9. 528
      alethzero/Main.ui
  10. 700
      alethzero/MainWin.cpp
  11. 186
      alethzero/MainWin.h
  12. 13
      alethzero/NatspecHandler.cpp
  13. 5
      alethzero/NatspecHandler.h
  14. 71
      alethzero/OurWebThreeStubServer.cpp
  15. 4
      alethzero/OurWebThreeStubServer.h
  16. 336
      alethzero/Transact.cpp
  17. 82
      alethzero/Transact.h
  18. 244
      alethzero/Transact.ui
  19. 3
      cmake/EthCompilerSettings.cmake
  20. 4
      cmake/EthDependencies.cmake
  21. 47
      cmake/FindMHD.cmake
  22. 8
      extdep/CMakeLists.txt
  23. 5
      libdevcore/vector_ref.h
  24. 10
      libethcore/CommonEth.cpp
  25. 33
      libethcore/CommonEth.h
  26. 13
      libethcore/CommonJS.cpp
  27. 3
      libethcore/CommonJS.h
  28. 4
      libethereum/BlockChain.h
  29. 6
      libethereum/Executive.cpp
  30. 5
      libethereum/Executive.h
  31. 4
      libjsqrc/setup.js
  32. 6
      libp2p/NodeTable.h
  33. 41
      libqwebthree/CMakeLists.txt
  34. 107
      libqwebthree/QWebThree.cpp
  35. 89
      libqwebthree/QWebThree.h
  36. 12
      libsolidity/AST.cpp
  37. 39
      libsolidity/AST.h
  38. 2
      libsolidity/ASTForward.h
  39. 22
      libsolidity/ASTPrinter.cpp
  40. 4
      libsolidity/ASTPrinter.h
  41. 8
      libsolidity/ASTVisitor.h
  42. 28
      libsolidity/AST_accept.h
  43. 5
      libsolidity/CompilerStack.cpp
  44. 1
      libsolidity/CompilerStack.h
  45. 28
      libsolidity/ExpressionCompiler.cpp
  46. 19
      libsolidity/NameAndTypeResolver.cpp
  47. 3
      libsolidity/NameAndTypeResolver.h
  48. 35
      libsolidity/Parser.cpp
  49. 2
      libsolidity/Parser.h
  50. 80
      libsolidity/Token.h
  51. 48
      libsolidity/Types.cpp
  52. 33
      libsolidity/Types.h
  53. 5
      libsolidity/grammar.txt
  54. 5
      libweb3jsonrpc/CMakeLists.txt
  55. 28
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  56. 26
      libweb3jsonrpc/WebThreeStubServerBase.h
  57. 146
      libweb3jsonrpc/abstractwebthreestubserver.h
  58. 2
      mix/Web3Server.cpp
  59. 2
      mix/Web3Server.h
  60. 2
      mix/qml/BasicMessage.qml
  61. 3
      mix/qml/CodeEditorView.qml
  62. 6
      mix/qml/Debugger.qml
  63. 2
      mix/qml/StateList.qml
  64. 2
      mix/qml/StateListModel.qml
  65. 2
      mix/qml/TransactionLog.qml
  66. 124
      mix/qml/WebPreview.qml
  67. 14
      mix/qml/WebPreviewStyle.qml
  68. BIN
      mix/qml/img/available_updates.png
  69. 1
      mix/qml/qmldir
  70. 2
      mix/res.qrc
  71. 17
      test/PerformaceTester.sol
  72. 35
      test/SolidityEndToEndTest.cpp
  73. 91
      test/SolidityNameAndTypeResolution.cpp
  74. 32
      test/SolidityParser.cpp
  75. 4
      test/vm.cpp
  76. 131
      test/vmPerformanceTestFiller.json
  77. 30
      test/webthreestubclient.h
  78. 5
      third/CMakeLists.txt
  79. 20
      third/MainWin.cpp
  80. 8
      third/MainWin.h

1
CMakeLists.txt

@ -181,7 +181,6 @@ if (NOT HEADLESS)
add_subdirectory(libnatspec)
add_subdirectory(libjsqrc)
add_subdirectory(libqwebthree)
add_subdirectory(alethzero)
add_subdirectory(third)
add_subdirectory(mix)

43
CodingStandards.txt

@ -1,8 +1,11 @@
0. Formatting
GOLDEN RULE: Never *ever* use spaces for formatting.
a. Use tabs for indentation!
- tab stops are every 4 characters.
- One indentation level -> exactly one byte (i.e. a tab character) in the source file.
- Never use spaces to line up sequential lines: If you have run-on lines, indent as you would for a block.
b. Line widths:
- Don't worry about having lines of code > 80-char wide.
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be prefered over beauty.
@ -17,10 +20,22 @@ j. Braces, when used, always have their own lines and are at same indentation le
(WRONG)
if( a==b[ i ] ) { printf ("Hello\n"); }
foo->bar(someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName);
(RIGHT)
if (a == b[i])
printf("Hello\n"); // NOTE spaces used instead of tab here for clarify - first byte should be '\t'.
printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
foo->bar(
someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName
);
@ -57,6 +72,8 @@ e. Split complex macro on multiple lines with '\'.
3. Capitalization;
GOLDEN RULE: Preprocessor: ALL_CAPS; C++: camelCase.
a. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
b. The following entities' first alpha is upper case:
- Type names.
@ -65,6 +82,7 @@ b. The following entities' first alpha is upper case:
- static const variables that form an external API.
c. All preprocessor symbols (macros, macro argments) in full uppercase with underscore word separation.
All other entities' first alpha is lower case.
@ -98,7 +116,7 @@ g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType".
i. Make use of auto whenever type is clear or unimportant:
- Always avoid doubly-stating the type.
- Use to avoid vast and unimportant type declarations
- Use to avoid vast and unimportant type declarations.
(WRONG)
@ -122,6 +140,7 @@ for (auto i = x.begin(); i != x.end(); ++i) {}
7. Structs & classes
a. Structs to be used when all members public and no virtual functions.
- In this case, members should be named naturally and not prefixed with 'm_'
b. Classes to be used in all other circumstances.
@ -131,7 +150,7 @@ b. Classes to be used in all other circumstances.
a. One member per line only.
b. Private, non-static, non-const fields prefixed with m_.
c. Avoid public fields, except in structs.
d. Use override, final and const judiciously.
d. Use override, final and const as much as possible.
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).
@ -154,14 +173,18 @@ c. Avoid unpronouncable names;
- If you need to shorten a name favour a pronouncable slice of the original to a scatterred set of consonants.
- e.g. Manager shortens to Man rather than Mgr.
d. Avoid prefixes of initials (e.g. DON'T use IMyInterface, CMyImplementation)
e. A dictionary and thesaurus are your friends.
e. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
- A dictionary and thesaurus are your friends.
- Spell correctly.
- Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
- Think carefully about the class's purpose.
- Imagine it as an isolated component to try to decontextualise it when considering its name.
- Don't be trapped into naming it (purely) in terms of its implementation.
10. Type-definitions
a. Prefer using to typedef. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;
a. Prefer 'using' to 'typedef'. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;
b. Generally avoid shortening a standard form that already includes all important information:
- e.g. stick to shared_ptr<X> rather than shortening to ptr<X>.
c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
@ -169,9 +192,17 @@ c. Where there are exceptions to this (due to excessive use and clear meaning),
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation.
b. Document the interface, not the implementation.
- Documentation should be able to remain completely unchanged, even if the method is reimplemented.
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports).
- Be careful to scrutinise documentation that extends only to intended purpose and usage.
- Reject documentation that is simply an English transaction of the implementation.
12. Include Headers

8
alethzero/CMakeLists.txt

@ -15,6 +15,8 @@ include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
qt5_wrap_ui(ui_Main.h Main.ui)
qt5_wrap_ui(ui_Debugger.h Debugger.ui)
qt5_wrap_ui(ui_Transact.h Transact.ui)
file(GLOB HEADERS "*.h")
@ -27,15 +29,17 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES alethzero.icns Main.ui
UI_RESOURCES alethzero.icns Main.ui Debugger.ui Transact.ui
WIN_RESOURCES alethzero.rc
)
add_dependencies(${EXECUTABLE} BuildInfo.h)
target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Widgets)
target_link_libraries(${EXECUTABLE} Qt5::WebKit)
target_link_libraries(${EXECUTABLE} Qt5::WebKitWidgets)
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} qwebthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} ethcore)

59
alethzero/Context.cpp

@ -0,0 +1,59 @@
/*
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 Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Context.h"
#include <QComboBox>
#include <libethcore/CommonEth.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
NatSpecFace::~NatSpecFace()
{
}
Context::~Context()
{
}
void initUnits(QComboBox* _b)
{
for (auto n = (unsigned)units().size(); n-- != 0; )
_b->addItem(QString::fromStdString(units()[n].second), n);
}
vector<KeyPair> keysAsVector(QList<KeyPair> const& keys)
{
auto list = keys.toStdList();
return {begin(list), end(list)};
}
bool sourceIsSolidity(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol");
}
bool sourceIsSerpent(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 5) == "//ser");
}

68
alethzero/Context.h

@ -0,0 +1,68 @@
/*
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 Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <string>
#include <vector>
#include <QString>
#include <QList>
#include <libethcore/CommonEth.h>
class QComboBox;
namespace dev { namespace eth { class StateDiff; } }
#define Small "font-size: small; "
#define Mono "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; "
#define Div(S) "<div style=\"" S "\">"
#define Span(S) "<span style=\"" S "\">"
void initUnits(QComboBox* _b);
std::vector<dev::KeyPair> keysAsVector(QList<dev::KeyPair> const& _keys);
bool sourceIsSolidity(std::string const& _source);
bool sourceIsSerpent(std::string const& _source);
class NatSpecFace
{
public:
virtual ~NatSpecFace();
virtual void add(dev::h256 const& _contractHash, std::string const& _doc) = 0;
virtual std::string retrieve(dev::h256 const& _contractHash) const = 0;
virtual std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData) = 0;
virtual std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta) = 0;
};
class Context
{
public:
virtual ~Context();
virtual QString pretty(dev::Address _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0;
virtual QString render(dev::Address _a) const = 0;
virtual dev::Address fromString(QString const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
};

380
alethzero/Debugger.cpp

@ -0,0 +1,380 @@
/*
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 Debugger.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Debugger.h"
#include <fstream>
#include <QFileDialog>
#include <libevm/VM.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Executive.h>
#include "ui_Debugger.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
Debugger::Debugger(Context* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Debugger),
m_context(_c)
{
ui->setupUi(this);
}
Debugger::~Debugger()
{
delete ui;
}
void Debugger::init()
{
if (m_session.history.size())
{
alterDebugStateGroup(true);
ui->debugCode->setEnabled(false);
ui->debugTimeline->setMinimum(0);
ui->debugTimeline->setMaximum(m_session.history.size());
ui->debugTimeline->setValue(0);
}
}
void Debugger::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
{
finished();
if (m_session.populate(_executive, _transaction))
init();
update();
}
bool DebugSession::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
{
try {
if (_executive.setup(_transaction))
return false;
}
catch (...)
{
// Invalid transaction
return false;
}
vector<WorldState const*> levels;
bytes lastExtCode;
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, VM* voidVM, ExtVMFace const* voidExt)
{
VM& vm = *voidVM;
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
if (ext.code != lastExtCode)
{
lastExtCode = ext.code;
lastHash = sha3(lastExtCode);
if (!codes.count(lastHash))
codes[lastHash] = ext.code;
}
if (ext.data != lastData)
{
lastData = ext.data;
lastDataHash = sha3(lastData);
if (!codes.count(lastDataHash))
codes[lastDataHash] = ext.data.toBytes();
}
if (levels.size() < ext.depth)
levels.push_back(&history.back());
else
levels.resize(ext.depth);
history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
_executive.go(onOp);
_executive.finalize();
return true;
}
void Debugger::finished()
{
m_session = DebugSession();
ui->callStack->clear();
ui->debugCode->clear();
ui->debugStack->clear();
ui->debugMemory->setHtml("");
ui->debugStorage->setHtml("");
ui->debugStateInfo->setText("");
alterDebugStateGroup(false);
}
void Debugger::update()
{
if (m_session.history.size())
{
WorldState const& nws = m_session.history[min((int)m_session.history.size() - 1, ui->debugTimeline->value())];
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
if (ui->debugTimeline->value() >= m_session.history.size())
{
if (ws.gasCost > ws.gas)
ui->debugMemory->setHtml("<h3>OUT-OF-GAS</h3>");
else if (ws.inst == Instruction::RETURN && ws.stack.size() >= 2)
{
unsigned from = (unsigned)ws.stack.back();
unsigned size = (unsigned)ws.stack[ws.stack.size() - 2];
unsigned o = 0;
bytes out(size, 0);
for (; o < size && from + o < ws.memory.size(); ++o)
out[o] = ws.memory[from + o];
ui->debugMemory->setHtml("<h3>RETURN</h3>" + QString::fromStdString(dev::memDump(out, 16, true)));
}
else if (ws.inst == Instruction::STOP)
ui->debugMemory->setHtml("<h3>STOP</h3>");
else if (ws.inst == Instruction::SUICIDE && ws.stack.size() >= 1)
ui->debugMemory->setHtml("<h3>SUICIDE</h3>0x" + QString::fromStdString(toString(right160(ws.stack.back()))));
else
ui->debugMemory->setHtml("<h3>EXCEPTION</h3>");
ostringstream ss;
ss << dec << "EXIT | GAS: " << dec << max<dev::bigint>(0, (dev::bigint)ws.gas - ws.gasCost);
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
ui->debugStorage->setHtml("");
ui->debugCallData->setHtml("");
m_session.currentData = h256();
ui->callStack->clear();
m_session.currentLevels.clear();
ui->debugCode->clear();
m_session.currentCode = h256();
ui->debugStack->setHtml("");
}
else
{
if (m_session.currentLevels != nws.levels || !ui->callStack->count())
{
m_session.currentLevels = nws.levels;
ui->callStack->clear();
for (unsigned i = 0; i <= nws.levels.size(); ++i)
{
WorldState const& s = i ? *nws.levels[nws.levels.size() - i] : nws;
ostringstream out;
out << s.cur.abridged();
if (i)
out << " " << instructionInfo(s.inst).name << " @0x" << hex << s.curPC;
ui->callStack->addItem(QString::fromStdString(out.str()));
}
}
if (ws.code != m_session.currentCode)
{
m_session.currentCode = ws.code;
bytes const& code = m_session.codes[ws.code];
QListWidget* dc = ui->debugCode;
dc->clear();
m_session.pcWarp.clear();
for (unsigned i = 0; i <= code.size(); ++i)
{
byte b = i < code.size() ? code[i] : 0;
try
{
QString s = QString::fromStdString(instructionInfo((Instruction)b).name);
ostringstream out;
out << hex << setw(4) << setfill('0') << i;
m_session.pcWarp[i] = dc->count();
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32)
{
unsigned bc = b - (byte)Instruction::PUSH1 + 1;
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc)));
i += bc;
}
dc->addItem(QString::fromStdString(out.str()) + " " + s);
}
catch (...)
{
cerr << "Unhandled exception!" << endl << boost::current_exception_diagnostic_information();
break; // probably hit data segment
}
}
}
if (ws.callData != m_session.currentData)
{
m_session.currentData = ws.callData;
if (ws.callData)
{
assert(m_session.codes.count(ws.callData));
ui->debugCallData->setHtml(QString::fromStdString(dev::memDump(m_session.codes[ws.callData], 16, true)));
}
else
ui->debugCallData->setHtml("");
}
QString stack;
for (auto i: ws.stack)
stack.prepend("<div>" + m_context->prettyU256(i) + "</div>");
ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_session.codes.count(ws.code));
if (m_session.codes[ws.code].size() >= (unsigned)ws.curPC)
{
int l = m_session.pcWarp[(unsigned)ws.curPC];
ui->debugCode->setCurrentRow(max(0, l - 5));
ui->debugCode->setCurrentRow(min(ui->debugCode->count() - 1, l + 5));
ui->debugCode->setCurrentRow(l);
}
else
cwarn << "PC (" << (unsigned)ws.curPC << ") is after code range (" << m_session.codes[ws.code].size() << ")";
ostringstream ss;
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)
s << "@" << m_context->prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << m_context->prettyU256(i.second).toStdString() << "<br/>";
ui->debugStorage->setHtml(QString::fromStdString(s.str()));
}
}
}
void Debugger::on_callStack_currentItemChanged()
{
update();
}
void Debugger::alterDebugStateGroup(bool _enable) const
{
ui->stepOver->setEnabled(_enable);
ui->stepInto->setEnabled(_enable);
ui->stepOut->setEnabled(_enable);
ui->backOver->setEnabled(_enable);
ui->backInto->setEnabled(_enable);
ui->backOut->setEnabled(_enable);
ui->dump->setEnabled(_enable);
ui->dumpStorage->setEnabled(_enable);
ui->dumpPretty->setEnabled(_enable);
}
void Debugger::on_debugTimeline_valueChanged()
{
update();
}
void Debugger::on_stepOver_clicked()
{
if (ui->debugTimeline->value() < m_session.history.size()) {
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if ((ui->debugTimeline->value() + 1) < m_session.history.size() && m_session.history[ui->debugTimeline->value() + 1].levels.size() > l)
{
on_stepInto_clicked();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_stepOut_clicked();
}
else
on_stepInto_clicked();
}
}
void Debugger::on_stepInto_clicked()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() + 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_stepOut_clicked()
{
if (ui->debugTimeline->value() < m_session.history.size())
{
auto ls = m_session.history[ui->debugTimeline->value()].levels.size();
auto l = ui->debugTimeline->value();
for (; l < m_session.history.size() && m_session.history[l].levels.size() >= ls; ++l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_backInto_clicked()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() - 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_backOver_clicked()
{
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if (ui->debugTimeline->value() > 0 && m_session.history[ui->debugTimeline->value() - 1].levels.size() > l)
{
on_backInto_clicked();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_backOut_clicked();
}
else
on_backInto_clicked();
}
void Debugger::on_backOut_clicked()
{
if (ui->debugTimeline->value() > 0 && m_session.history.size() > 0)
{
auto ls = m_session.history[min(ui->debugTimeline->value(), m_session.history.size() - 1)].levels.size();
int l = ui->debugTimeline->value();
for (; l > 0 && m_session.history[l].levels.size() >= ls; --l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_dump_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
void Debugger::on_dumpPretty_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
f << endl << " STACK" << endl;
for (auto i: ws.stack)
f << (h256)i << endl;
f << " MEMORY" << endl << dev::memDump(ws.memory);
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 << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
}
}
void Debugger::on_dumpStorage_clicked()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE)
for (auto i: ws.storage)
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
}

103
alethzero/Debugger.h

@ -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 Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <QDialog>
#include <QMap>
#include <QList>
#include "Context.h"
namespace Ui { class Debugger; }
struct WorldState
{
uint64_t steps;
dev::Address cur;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::h256 code;
dev::h256 callData;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<WorldState const*> levels;
};
struct DebugSession
{
DebugSession() {}
bool populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction);
dev::h256 currentCode;
dev::h256 currentData;
std::vector<WorldState const*> currentLevels;
QMap<unsigned, unsigned> pcWarp;
QList<WorldState> history;
std::map<dev::u256, dev::bytes> codes;
};
class Debugger: public QDialog
{
Q_OBJECT
public:
explicit Debugger(Context* _context, QWidget* _parent = 0);
~Debugger();
void populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction);
protected slots:
void on_callStack_currentItemChanged();
void on_debugTimeline_valueChanged();
void on_stepOver_clicked();
void on_stepInto_clicked();
void on_stepOut_clicked();
void on_backOver_clicked();
void on_backInto_clicked();
void on_backOut_clicked();
void on_dump_clicked();
void on_dumpPretty_clicked();
void on_dumpStorage_clicked();
void on_close_clicked() { close(); }
private:
void init();
void update();
void finished();
void alterDebugStateGroup(bool _enable) const;
Ui::Debugger* ui;
DebugSession m_session;
Context* m_context;
};

300
alethzero/Debugger.ui

@ -0,0 +1,300 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Debugger</class>
<widget class="QDialog" name="Debugger">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>989</width>
<height>690</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="stepOver">
<property name="text">
<string>Step Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepInto">
<property name="text">
<string>Step Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepOut">
<property name="text">
<string>Step Out</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOver">
<property name="text">
<string>Back Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backInto">
<property name="text">
<string>Back Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOut">
<property name="text">
<string>Back Out</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="debugCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QListWidget" name="callStack">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</widget>
<widget class="QSplitter" name="splitter_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTextEdit" name="debugStack">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugMemory">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugStorage">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugCallData">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="debugStateInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="debugTimeline">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="dump">
<property name="text">
<string>Dump</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpStorage">
<property name="text">
<string>Dump Storage</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpPretty">
<property name="text">
<string>Dump Pretty</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>577</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

528
alethzero/Main.ui

@ -117,7 +117,7 @@
<x>0</x>
<y>0</y>
<width>1617</width>
<height>25</height>
<height>24</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
@ -140,11 +140,12 @@
</widget>
<widget class="QMenu" name="menu_Tools">
<property name="title">
<string>T&amp;ools</string>
<string>&amp;Tools</string>
</property>
<addaction name="mine"/>
<addaction name="separator"/>
<addaction name="create"/>
<addaction name="newTransaction"/>
<addaction name="newAccount"/>
<addaction name="importKey"/>
<addaction name="importKeyFile"/>
<addaction name="exportKey"/>
@ -160,18 +161,14 @@
</widget>
<widget class="QMenu" name="menu_Debug">
<property name="title">
<string>Deb&amp;ug</string>
<string>&amp;Special</string>
</property>
<addaction name="debugDumpState"/>
<addaction name="debugDumpStatePre"/>
<addaction name="separator"/>
<addaction name="paranoia"/>
<addaction name="clearPending"/>
<addaction name="killBlockchain"/>
<addaction name="inject"/>
<addaction name="forceMining"/>
<addaction name="turboMining"/>
<addaction name="enableOptimizer"/>
<addaction name="separator"/>
<addaction name="usePrivate"/>
<addaction name="jitvm"/>
@ -185,42 +182,28 @@
<addaction name="separator"/>
<addaction name="preview"/>
</widget>
<widget class="QMenu" name="menuDebugger">
<property name="title">
<string>D&amp;ebugger</string>
</property>
<widget class="QMenu" name="menu_Dump_Trace">
<property name="title">
<string>&amp;Dump Trace</string>
</property>
<addaction name="dumpTrace"/>
<addaction name="dumpTraceStorage"/>
<addaction name="dumpTracePretty"/>
</widget>
<addaction name="debugCurrent"/>
<addaction name="menu_Dump_Trace"/>
<addaction name="separator"/>
<addaction name="debugStep"/>
<addaction name="debugStepInto"/>
<addaction name="debugStepOut"/>
<addaction name="debugStepBack"/>
<addaction name="debugStepBackInto"/>
<addaction name="debugStepBackOut"/>
</widget>
<widget class="QMenu" name="menuWhispe">
<property name="title">
<string>&amp;Whisper</string>
</property>
<addaction name="newIdentity"/>
</widget>
<widget class="QMenu" name="menuDebug">
<property name="title">
<string>&amp;Debug</string>
</property>
<addaction name="debugCurrent"/>
<addaction name="debugDumpState"/>
<addaction name="debugDumpStatePre"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_View"/>
<addaction name="menu_Network"/>
<addaction name="menu_Tools"/>
<addaction name="menuDebugger"/>
<addaction name="menuWhispe"/>
<addaction name="menu_Debug"/>
<addaction name="menuDebug"/>
<addaction name="menu_Help"/>
<addaction name="menu_Debug"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_2">
@ -533,237 +516,11 @@
<bool>false</bool>
</attribute>
<addaction name="go"/>
<addaction name="newTransaction"/>
<addaction name="preview"/>
<addaction name="mine"/>
<addaction name="refresh"/>
</widget>
<widget class="QDockWidget" name="dockWidget_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>510</width>
<height>386</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Transact</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Data</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property>
<property name="buddy">
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="gas">
<property name="suffix">
<string> gas</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Amount</string>
</property>
<property name="buddy">
<cstring>value</cstring>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QLabel" name="fee">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="destination">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>(Create Contract)</string>
</property>
</item>
</widget>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="send">
<property name="text">
<string>&amp;Execute</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>De&amp;bug</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_7">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
@ -987,171 +744,6 @@
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_9">
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Debugger</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="debugPanel">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="debugCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QListWidget" name="callStack">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</widget>
<widget class="QSplitter" name="splitter_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTextEdit" name="debugStack">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugMemory">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugStorage">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugCallData">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="debugStateInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="debugTimeline">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_10">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
@ -1566,9 +1158,6 @@ font-size: 14pt</string>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
@ -1621,9 +1210,6 @@ font-size: 14pt</string>
<property name="text">
<string>TTL</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
@ -1637,9 +1223,6 @@ font-size: 14pt</string>
<property name="text">
<string>From</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
@ -1653,9 +1236,6 @@ font-size: 14pt</string>
<property name="text">
<string>To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
@ -1686,9 +1266,6 @@ font-size: 14pt</string>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
@ -1715,9 +1292,6 @@ font-size: 14pt</string>
<property name="text">
<string>Work to Prove</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
</layout>
@ -1776,7 +1350,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Use &amp;UPnP</string>
<string>&amp;Use UPnP</string>
</property>
</action>
<action name="connect">
@ -1800,9 +1374,9 @@ font-size: 14pt</string>
<string>&amp;Mine</string>
</property>
</action>
<action name="create">
<action name="newAccount">
<property name="text">
<string>&amp;New Address</string>
<string>&amp;New Address...</string>
</property>
</action>
<action name="about">
@ -1834,7 +1408,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Mining &amp;Paranoia</string>
<string>&amp;Mining Paranoia</string>
</property>
</action>
<action name="killBlockchain">
@ -1862,7 +1436,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Show Ancient &amp;Blocks</string>
<string>&amp;Show Ancient Blocks</string>
</property>
</action>
<action name="showAllAccounts">
@ -1870,7 +1444,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Show Anonymous &amp;Accounts</string>
<string>Show &amp;Anonymous Accounts</string>
</property>
</action>
<action name="usePast">
@ -1970,7 +1544,7 @@ font-size: 14pt</string>
<bool>false</bool>
</property>
<property name="text">
<string>Debu&amp;g Current Transaction</string>
<string>&amp;Debug Current Transaction</string>
</property>
</action>
<action name="debugDumpState">
@ -1978,7 +1552,7 @@ font-size: 14pt</string>
<bool>false</bool>
</property>
<property name="text">
<string>D&amp;ump Current Transaction State (post)</string>
<string>Dump &amp;Current Transaction State (post)</string>
</property>
</action>
<action name="debugDumpStatePre">
@ -1986,7 +1560,7 @@ font-size: 14pt</string>
<bool>false</bool>
</property>
<property name="text">
<string>D&amp;ump Current Transaction State (pre)</string>
<string>Dump Current &amp;Transaction State (pre)</string>
</property>
</action>
<action name="dumpTracePretty">
@ -2007,7 +1581,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Use Private Chain...</string>
<string>Use &amp;Private Chain...</string>
</property>
</action>
<action name="enableOptimizer">
@ -2015,7 +1589,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Enable LLL &amp;Optimizer</string>
<string>&amp;Enable LLL Optimizer</string>
</property>
</action>
<action name="turboMining">
@ -2023,7 +1597,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Reserved Debug 1</string>
<string>&amp;Reserved Debug 1</string>
</property>
</action>
<action name="localNetworking">
@ -2031,7 +1605,7 @@ font-size: 14pt</string>
<bool>true</bool>
</property>
<property name="text">
<string>Enable Local Addresses</string>
<string>&amp;Enable Local Addresses</string>
</property>
</action>
<action name="importKeyFile">
@ -2044,7 +1618,7 @@ font-size: 14pt</string>
</action>
<action name="go">
<property name="text">
<string>Go!</string>
<string>&amp;Go!</string>
</property>
</action>
<action name="newIdentity">
@ -2054,7 +1628,7 @@ font-size: 14pt</string>
</action>
<action name="clearPending">
<property name="text">
<string>Clear Pe&amp;nd&amp;ing</string>
<string>&amp;Clear Pending</string>
</property>
</action>
<action name="jitvm">
@ -2073,6 +1647,11 @@ font-size: 14pt</string>
<string>&amp;Kill Account</string>
</property>
</action>
<action name="newTransaction">
<property name="text">
<string>New &amp;Transaction...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -2095,27 +1674,30 @@ font-size: 14pt</string>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>destination</tabstop>
<tabstop>calculatedName</tabstop>
<tabstop>value</tabstop>
<tabstop>valueUnits</tabstop>
<tabstop>gas</tabstop>
<tabstop>gasPrice</tabstop>
<tabstop>gasPriceUnits</tabstop>
<tabstop>data</tabstop>
<tabstop>send</tabstop>
<tabstop>idealPeers</tabstop>
<tabstop>port</tabstop>
<tabstop>clientName</tabstop>
<tabstop>shhTo</tabstop>
<tabstop>shhFrom</tabstop>
<tabstop>shhTtl</tabstop>
<tabstop>shhTopic</tabstop>
<tabstop>shhWork</tabstop>
<tabstop>shhData</tabstop>
<tabstop>log</tabstop>
<tabstop>post</tabstop>
<tabstop>verbosity</tabstop>
<tabstop>jsConsole</tabstop>
<tabstop>tabWidget</tabstop>
<tabstop>urlEdit</tabstop>
<tabstop>webView</tabstop>
<tabstop>idealPeers</tabstop>
<tabstop>forceAddress</tabstop>
<tabstop>port</tabstop>
<tabstop>clientName</tabstop>
<tabstop>transactionQueue</tabstop>
<tabstop>pendingInfo</tabstop>
<tabstop>blockChainFilter</tabstop>
<tabstop>nameReg</tabstop>
<tabstop>debugCode</tabstop>
<tabstop>debugStack</tabstop>
<tabstop>debugMemory</tabstop>
<tabstop>debugStorage</tabstop>
<tabstop>nodes</tabstop>
<tabstop>whispers</tabstop>
<tabstop>jsInput</tabstop>
</tabstops>
<resources/>
<connections/>

700
alethzero/MainWin.cpp

@ -50,11 +50,14 @@
#include <libethereum/EthereumHost.h>
#include <libethereum/DownloadMan.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include "MainWin.h"
#include "DownloadView.h"
#include "MiningView.h"
#include "BuildInfo.h"
#include "OurWebThreeStubServer.h"
#include "Transact.h"
#include "Debugger.h"
#include "ui_Main.h"
using namespace std;
using namespace dev;
@ -62,17 +65,6 @@ using namespace dev::p2p;
using namespace dev::eth;
namespace js = json_spirit;
#define Small "font-size: small; "
#define Mono "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; "
#define Div(S) "<div style=\"" S "\">"
#define Span(S) "<span style=\"" S "\">"
static void initUnits(QComboBox* _b)
{
for (auto n = (unsigned)units().size(); n-- != 0; )
_b->addItem(QString::fromStdString(units()[n].second), n);
}
QString Main::fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
@ -98,12 +90,6 @@ QString Main::fromRaw(h256 _n, unsigned* _inc)
return QString();
}
static vector<KeyPair> keysAsVector(QList<KeyPair> const& keys)
{
auto list = keys.toStdList();
return {begin(list), end(list)};
}
QString contentsOfQResource(string const& res)
{
QFile file(QString::fromStdString(res));
@ -119,7 +105,8 @@ Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
Main::Main(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Main)
ui(new Ui::Main),
m_transact(this, this)
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
@ -148,12 +135,6 @@ Main::Main(QWidget *parent) :
ui->configDock->close();
on_verbosity_valueChanged();
initUnits(ui->gasPriceUnits);
initUnits(ui->valueUnits);
ui->valueUnits->setCurrentIndex(6);
ui->gasPriceUnits->setCurrentIndex(4);
ui->gasPrice->setValue(10);
on_destination_currentTextChanged();
statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount);
@ -167,25 +148,26 @@ Main::Main(QWidget *parent) :
bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size());
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"}, p2p::NetworkPreferences(), network));
m_qwebConnector.reset(new QWebThreeConnector());
m_server.reset(new OurWebThreeStubServer(*m_qwebConnector, *web3(), keysAsVector(m_myKeys), this));
m_httpConnector.reset(new jsonrpc::HttpServer(8080));
m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys), this));
connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString)));
m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening();
connect(ui->webView, &QWebView::loadStarted, [this]()
{
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_qweb = new QWebThree(this);
auto qweb = m_qweb;
m_qwebConnector->setQWeb(qweb);
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb));
connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString)));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, [f, this]()
{
f->disconnect();
f->addToJavaScriptWindowObject("env", this, QWebFrame::QtOwnership);
f->evaluateJavaScript(contentsOfQResource(":/js/bignumber.min.js"));
f->evaluateJavaScript(contentsOfQResource(":/js/webthree.js"));
f->evaluateJavaScript(contentsOfQResource(":/js/setup.js"));
});
});
connect(ui->webView, &QWebView::loadFinished, [=]()
@ -216,7 +198,6 @@ Main::~Main()
writeSettings();
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
m_qweb->clientDieing();
g_logPost = simpleDebugOut;
}
@ -372,12 +353,6 @@ void Main::on_forceMining_triggered()
ethereum()->setForceMining(ui->forceMining->isChecked());
}
void Main::on_enableOptimizer_triggered()
{
m_enableOptimizer = ui->enableOptimizer->isChecked();
on_data_textChanged();
}
QString Main::contents(QString _s)
{
return QString::fromStdString(dev::asString(dev::contents(_s.toStdString())));
@ -411,6 +386,12 @@ void Main::load(QString _s)
}*/
}
void Main::on_newTransaction_triggered()
{
m_transact.setEnvironment(m_myKeys, ethereum(), &m_natSpecDB);
m_transact.exec();
}
void Main::on_loadJS_triggered()
{
QString f = QFileDialog::getOpenFileName(this, "Load Javascript", QString(), "Javascript (*.js);;All files (*)");
@ -672,7 +653,6 @@ void Main::writeSettings()
s.setValue("paranoia", ui->paranoia->isChecked());
s.setValue("showAll", ui->showAll->isChecked());
s.setValue("showAllAccounts", ui->showAllAccounts->isChecked());
s.setValue("enableOptimizer", m_enableOptimizer);
s.setValue("clientName", ui->clientName->text());
s.setValue("idealPeers", ui->idealPeers->value());
s.setValue("port", ui->port->value());
@ -742,8 +722,6 @@ void Main::readSettings(bool _skipGeometry)
ui->paranoia->setChecked(s.value("paranoia", false).toBool());
ui->showAll->setChecked(s.value("showAll", false).toBool());
ui->showAllAccounts->setChecked(s.value("showAllAccounts", false).toBool());
m_enableOptimizer = s.value("enableOptimizer", true).toBool();
ui->enableOptimizer->setChecked(m_enableOptimizer);
ui->clientName->setText(s.value("clientName", "").toString());
if (ui->clientName->text().isEmpty())
ui->clientName->setText(QInputDialog::getText(nullptr, "Enter identity", "Enter a name that will identify you on the peer network"));
@ -990,7 +968,6 @@ void Main::refreshNetwork()
void Main::refreshAll()
{
refreshDestination();
refreshBlockChain();
refreshBlockCount();
refreshPending();
@ -1041,20 +1018,6 @@ void Main::refreshAccounts()
}
}
void Main::refreshDestination()
{
cwatch << "refreshDestination()";
QString s;
for (auto i: ethereum()->addresses())
if ((s = pretty(i)).size())
// A namereg address
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !fromString(ui->destination->itemText(i)))
ui->destination->removeItem(i--);
}
void Main::refreshBlockCount()
{
cwatch << "refreshBlockCount()";
@ -1477,13 +1440,12 @@ void Main::on_debugCurrent_triggered()
if (!item->data(Qt::UserRole + 1).isNull())
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
m_executiveState = ethereum()->state(txi + 1, h);
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState, ethereum()->blockChain(), 0));
Transaction t = m_executiveState.pending()[txi];
m_executiveState = m_executiveState.fromPending(txi);
auto r = t.rlp();
populateDebugger(&r);
m_currentExecution.reset();
bytes t = ethereum()->blockChain().transaction(h, txi);
State s(ethereum()->state(txi, h));
Executive e(s, ethereum()->blockChain(), 0);
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckSignature::Sender));
dw.exec();
}
}
}
@ -1514,49 +1476,6 @@ void Main::on_debugDumpStatePre_triggered()
on_debugDumpState_triggered(0);
}
void Main::populateDebugger(dev::bytesConstRef _r)
{
bool done = m_currentExecution->setup(_r);
if (!done)
{
debugFinished();
vector<WorldState const*> levels;
m_codes.clear();
bytes lastExtCode;
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, VM* voidVM, ExtVMFace const* voidExt)
{
VM& vm = *voidVM;
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
if (ext.code != lastExtCode)
{
lastExtCode = ext.code;
lastHash = sha3(lastExtCode);
if (!m_codes.count(lastHash))
m_codes[lastHash] = ext.code;
}
if (ext.data != lastData)
{
lastData = ext.data;
lastDataHash = sha3(lastData);
if (!m_codes.count(lastDataHash))
m_codes[lastDataHash] = ext.data.toBytes();
}
if (levels.size() < ext.depth)
levels.push_back(&m_history.back());
else
levels.resize(ext.depth);
m_history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
m_currentExecution->go(onOp);
m_currentExecution->finalize();
initDebugger();
updateDebugger();
}
}
void Main::on_contracts_currentItemChanged()
{
ui->contractInfo->clear();
@ -1572,7 +1491,7 @@ void Main::on_contracts_currentItemChanged()
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second).toStdString() << "<br/>";
s << "<h4>Body Code</h4>" << disassemble(ethereum()->codeAt(address));
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << Div(Mono) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->contractInfo->appendHtml(QString::fromStdString(s.str()));
}
@ -1616,19 +1535,6 @@ void Main::on_contracts_doubleClicked()
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
void Main::on_destination_currentTextChanged()
{
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
if (Address a = fromString(ui->destination->currentText()))
ui->calculatedName->setText(render(a));
else
ui->calculatedName->setText("Unknown Address");
else
ui->calculatedName->setText("Create Contract");
on_data_textChanged();
// updateFee();
}
static shh::FullTopic topicFromText(QString _s)
{
shh::BuildTopic ret;
@ -1683,134 +1589,6 @@ static shh::FullTopic 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");
}
static bool sourceIsSerpent(string const& _source)
{
// TODO: Improve this heuristic
return (_source.substr(0, 5) == "//ser");
}
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->getDeclaration().getName() + "\n";
}
return ret;
}
void Main::on_data_textChanged()
{
m_pcWarp.clear();
if (isCreation())
{
string src = ui->data->toPlainText().toStdString();
vector<string> errors;
QString lll;
QString solidity;
if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0)
{
m_data = fromHex(src);
}
else if (sourceIsSolidity(src))
{
dev::solidity::CompilerStack compiler;
try
{
// compiler.addSources(dev::solidity::StandardSources);
m_data = compiler.compile(src, m_enableOptimizer);
solidity = "<h4>Solidity</h4>";
solidity += "<pre>var " + QString::fromStdString(compiler.getContractNames().front()) + " = web3.eth.contractFromAbi(" + 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)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>";
}
catch (...)
{
solidity = "<h4>Solidity</h4><pre>Uncaught exception.</pre>";
}
}
#ifndef _MSC_VER
else if (sourceIsSerpent(src))
{
try
{
m_data = dev::asBytes(::compile(src));
for (auto& i: errors)
i = "(LLL " + i + ")";
}
catch (string err)
{
errors.push_back("Serpent " + err);
}
}
#endif
else
{
m_data = compileLLL(src, m_enableOptimizer, &errors);
if (errors.empty())
{
auto asmcode = compileLLLToAsm(src, false);
lll = "<h4>Pre</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>";
if (m_enableOptimizer)
{
asmcode = compileLLLToAsm(src, true);
lll = "<h4>Opt</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>" + lll;
}
}
}
QString errs;
if (errors.size())
{
errs = "<h4>Errors</h4>";
for (auto const& i: errors)
errs.append("<div style=\"border-left: 6px solid #c00; margin-top: 2px\">" + QString::fromStdString(i).toHtmlEscaped() + "</div>");
}
ui->code->setHtml(errs + lll + solidity + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped() + "<h4>Hex</h4>" Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>");
ui->gas->setMinimum((qint64)Client::txGas(m_data, 0));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
}
else
{
m_data = parseData(ui->data->toPlainText().toStdString());
ui->code->setHtml(QString::fromStdString(dev::memDump(m_data, 8, true)));
if (ethereum()->codeAt(fromString(ui->destination->currentText()), 0).size())
{
ui->gas->setMinimum((qint64)Client::txGas(m_data, 1));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
}
else
{
if (ui->gas->isEnabled())
m_backupGas = ui->gas->value();
ui->gas->setValue((qint64)Client::txGas(m_data));
ui->gas->setEnabled(false);
}
}
updateFee();
}
void Main::on_clearPending_triggered()
{
writeSettings();
@ -1835,54 +1613,6 @@ void Main::on_killBlockchain_triggered()
refreshAll();
}
bool Main::isCreation() const
{
return ui->destination->currentText().isEmpty() || ui->destination->currentText() == "(Create Contract)";
}
u256 Main::fee() const
{
return ui->gas->value() * gasPrice();
}
u256 Main::value() const
{
if (ui->valueUnits->currentIndex() == -1)
return 0;
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first;
}
u256 Main::gasPrice() const
{
if (ui->gasPriceUnits->currentIndex() == -1)
return 0;
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first;
}
u256 Main::total() const
{
return value() + fee();
}
void Main::updateFee()
{
ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str()));
auto totalReq = total();
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str()));
bool ok = false;
for (auto i: m_myKeys)
if (ethereum()->balanceAt(i.address()) >= totalReq)
{
ok = true;
break;
}
ui->send->setEnabled(ok);
QPalette p = ui->total->palette();
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00));
ui->total->setPalette(p);
}
void Main::on_net_triggered()
{
ui->port->setEnabled(!ui->net->isChecked());
@ -1944,79 +1674,12 @@ void Main::on_mine_triggered()
ethereum()->stopMining();
}
void Main::on_send_clicked()
{
u256 totalReq = value() + fee();
for (auto i: m_myKeys)
if (ethereum()->balanceAt(i.address(), 0) >= totalReq)
{
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::NatspecUser));
}
}
catch (...)
{
statusBar()->showMessage("Couldn't compile Solidity Contract.");
}
}
else
ethereum()->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
return;
}
statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount.");
}
void Main::keysChanged()
{
onBalancesChange();
m_server->setAccounts(keysAsVector(m_myKeys));
}
void Main::on_debug_clicked()
{
debugFinished();
try
{
u256 totalReq = value() + fee();
for (auto i: m_myKeys)
if (ethereum()->balanceAt(i.address()) >= totalReq)
{
Secret s = i.secret();
m_executiveState = ethereum()->postState();
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState, ethereum()->blockChain(), 0));
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s);
auto r = t.rlp();
populateDebugger(&r);
m_currentExecution.reset();
return;
}
statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount.");
}
catch (dev::Exception const& _e)
{
statusBar()->showMessage("Error running transaction: " + QString::fromStdString(diagnostic_information(_e)));
// this output is aimed at developers, reconsider using _e.what for more user friendly output.
}
}
bool beginsWith(Address _a, bytes const& _b)
{
for (unsigned i = 0; i < min<unsigned>(20, _b.size()); ++i)
@ -2025,7 +1688,7 @@ bool beginsWith(Address _a, bytes const& _b)
return true;
}
void Main::on_create_triggered()
void Main::on_newAccount_triggered()
{
bool ok = true;
enum { NoVanity = 0, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch };
@ -2093,111 +1756,6 @@ void Main::on_killAccount_triggered()
}
}
void Main::on_debugStep_triggered()
{
if (ui->debugTimeline->value() < m_history.size()) {
auto l = m_history[ui->debugTimeline->value()].levels.size();
if ((ui->debugTimeline->value() + 1) < m_history.size() && m_history[ui->debugTimeline->value() + 1].levels.size() > l)
{
on_debugStepInto_triggered();
if (m_history[ui->debugTimeline->value()].levels.size() > l)
on_debugStepOut_triggered();
}
else
on_debugStepInto_triggered();
}
}
void Main::on_debugStepInto_triggered()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() + 1);
ui->callStack->setCurrentRow(0);
}
void Main::on_debugStepOut_triggered()
{
if (ui->debugTimeline->value() < m_history.size())
{
auto ls = m_history[ui->debugTimeline->value()].levels.size();
auto l = ui->debugTimeline->value();
for (; l < m_history.size() && m_history[l].levels.size() >= ls; ++l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Main::on_debugStepBackInto_triggered()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() - 1);
ui->callStack->setCurrentRow(0);
}
void Main::on_debugStepBack_triggered()
{
auto l = m_history[ui->debugTimeline->value()].levels.size();
if (ui->debugTimeline->value() > 0 && m_history[ui->debugTimeline->value() - 1].levels.size() > l)
{
on_debugStepBackInto_triggered();
if (m_history[ui->debugTimeline->value()].levels.size() > l)
on_debugStepBackOut_triggered();
}
else
on_debugStepBackInto_triggered();
}
void Main::on_debugStepBackOut_triggered()
{
if (ui->debugTimeline->value() > 0 && m_history.size() > 0)
{
auto ls = m_history[min(ui->debugTimeline->value(), m_history.size() - 1)].levels.size();
int l = ui->debugTimeline->value();
for (; l > 0 && m_history[l].levels.size() >= ls; --l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Main::on_dumpTrace_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_history)
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
void Main::on_dumpTracePretty_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_history)
{
f << endl << " STACK" << endl;
for (auto i: ws.stack)
f << (h256)i << endl;
f << " MEMORY" << endl << dev::memDump(ws.memory);
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 << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
}
}
void Main::on_dumpTraceStorage_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_history)
{
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE)
for (auto i: ws.storage)
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
}
void Main::on_go_triggered()
{
if (!ui->net->isChecked())
@ -2208,60 +1766,6 @@ void Main::on_go_triggered()
web3()->connect(Host::pocHost());
}
void Main::on_callStack_currentItemChanged()
{
updateDebugger();
}
void Main::alterDebugStateGroup(bool _enable) const
{
ui->debugStep->setEnabled(_enable);
ui->debugStepInto->setEnabled(_enable);
ui->debugStepOut->setEnabled(_enable);
ui->debugStepBackInto->setEnabled(_enable);
ui->debugStepBackOut->setEnabled(_enable);
ui->dumpTrace->setEnabled(_enable);
ui->dumpTraceStorage->setEnabled(_enable);
ui->dumpTracePretty->setEnabled(_enable);
ui->debugStepBack->setEnabled(_enable);
ui->debugPanel->setEnabled(_enable);
}
void Main::debugFinished()
{
m_codes.clear();
m_pcWarp.clear();
m_history.clear();
m_lastLevels.clear();
m_lastCode = h256();
ui->callStack->clear();
ui->debugCode->clear();
ui->debugStack->clear();
ui->debugMemory->setHtml("");
ui->debugStorage->setHtml("");
ui->debugStateInfo->setText("");
alterDebugStateGroup(false);
// ui->send->setEnabled(true);
}
void Main::initDebugger()
{
// ui->send->setEnabled(false);
if (m_history.size())
{
alterDebugStateGroup(true);
ui->debugCode->setEnabled(false);
ui->debugTimeline->setMinimum(0);
ui->debugTimeline->setMaximum(m_history.size());
ui->debugTimeline->setValue(0);
}
}
void Main::on_debugTimeline_valueChanged()
{
updateDebugger();
}
QString Main::prettyU256(dev::u256 _n) const
{
unsigned inc = 0;
@ -2289,136 +1793,6 @@ QString Main::prettyU256(dev::u256 _n) const
return QString::fromStdString(s.str());
}
void Main::updateDebugger()
{
if (m_history.size())
{
WorldState const& nws = m_history[min((int)m_history.size() - 1, ui->debugTimeline->value())];
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
if (ui->debugTimeline->value() >= m_history.size())
{
if (ws.gasCost > ws.gas)
ui->debugMemory->setHtml("<h3>OUT-OF-GAS</h3>");
else if (ws.inst == Instruction::RETURN && ws.stack.size() >= 2)
{
unsigned from = (unsigned)ws.stack.back();
unsigned size = (unsigned)ws.stack[ws.stack.size() - 2];
unsigned o = 0;
bytes out(size, 0);
for (; o < size && from + o < ws.memory.size(); ++o)
out[o] = ws.memory[from + o];
ui->debugMemory->setHtml("<h3>RETURN</h3>" + QString::fromStdString(dev::memDump(out, 16, true)));
}
else if (ws.inst == Instruction::STOP)
ui->debugMemory->setHtml("<h3>STOP</h3>");
else if (ws.inst == Instruction::SUICIDE && ws.stack.size() >= 1)
ui->debugMemory->setHtml("<h3>SUICIDE</h3>0x" + QString::fromStdString(toString(right160(ws.stack.back()))));
else
ui->debugMemory->setHtml("<h3>EXCEPTION</h3>");
ostringstream ss;
ss << dec << "EXIT | GAS: " << dec << max<dev::bigint>(0, (dev::bigint)ws.gas - ws.gasCost);
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
ui->debugStorage->setHtml("");
ui->debugCallData->setHtml("");
m_lastData = h256();
ui->callStack->clear();
m_lastLevels.clear();
ui->debugCode->clear();
m_lastCode = h256();
ui->debugStack->setHtml("");
}
else
{
if (m_lastLevels != nws.levels || !ui->callStack->count())
{
m_lastLevels = nws.levels;
ui->callStack->clear();
for (unsigned i = 0; i <= nws.levels.size(); ++i)
{
WorldState const& s = i ? *nws.levels[nws.levels.size() - i] : nws;
ostringstream out;
out << s.cur.abridged();
if (i)
out << " " << instructionInfo(s.inst).name << " @0x" << hex << s.curPC;
ui->callStack->addItem(QString::fromStdString(out.str()));
}
}
if (ws.code != m_lastCode)
{
bytes const& code = m_codes[ws.code];
QListWidget* dc = ui->debugCode;
dc->clear();
m_pcWarp.clear();
for (unsigned i = 0; i <= code.size(); ++i)
{
byte b = i < code.size() ? code[i] : 0;
try
{
QString s = QString::fromStdString(instructionInfo((Instruction)b).name);
ostringstream out;
out << hex << setw(4) << setfill('0') << i;
m_pcWarp[i] = dc->count();
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32)
{
unsigned bc = b - (byte)Instruction::PUSH1 + 1;
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc)));
i += bc;
}
dc->addItem(QString::fromStdString(out.str()) + " " + s);
}
catch (...)
{
cerr << "Unhandled exception!" << endl <<
boost::current_exception_diagnostic_information();
break; // probably hit data segment
}
}
m_lastCode = ws.code;
}
if (ws.callData != m_lastData)
{
m_lastData = ws.callData;
if (ws.callData)
{
assert(m_codes.count(ws.callData));
ui->debugCallData->setHtml(QString::fromStdString(dev::memDump(m_codes[ws.callData], 16, true)));
}
else
ui->debugCallData->setHtml("");
}
QString stack;
for (auto i: ws.stack)
stack.prepend("<div>" + prettyU256(i) + "</div>");
ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_codes.count(ws.code));
if (m_codes[ws.code].size() >= (unsigned)ws.curPC)
{
int l = m_pcWarp[(unsigned)ws.curPC];
ui->debugCode->setCurrentRow(max(0, l - 5));
ui->debugCode->setCurrentRow(min(ui->debugCode->count() - 1, l + 5));
ui->debugCode->setCurrentRow(l);
}
else
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 << " : " << 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)
s << "@" << prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << prettyU256(i.second).toStdString() << "<br/>";
ui->debugStorage->setHtml(QString::fromStdString(s.str()));
}
}
}
void Main::on_post_clicked()
{
shh::Message m;
@ -2431,14 +1805,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)
int Main::authenticate(QString _title, QString _text)
{
return m_natspecDB.getUserNotice(_contractHash, _transactionData);
QMessageBox userInput(this);
userInput.setText(_title);
userInput.setInformativeText(_text);
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();
}
void Main::refreshWhispers()

186
alethzero/MainWin.h

@ -34,10 +34,10 @@
#include <libethcore/CommonEth.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <libqwebthree/QWebThree.h>
#include <libwebthree/WebThree.h>
#include <libsolidity/CompilerStack.h>
#include "Context.h"
#include "Transact.h"
#include "NatspecHandler.h"
namespace Ui {
@ -49,31 +49,18 @@ class Client;
class State;
}}
namespace jsonrpc {
class HttpServer;
}
class QQuickView;
class OurWebThreeStubServer;
struct WorldState
{
uint64_t steps;
dev::Address cur;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::h256 code;
dev::h256 callData;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<WorldState const*> levels;
};
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
QString contentsOfQResource(std::string const& res);
class Main : public QMainWindow
class Main: public QMainWindow, public Context
{
Q_OBJECT
@ -85,13 +72,20 @@ 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& _contractHash) const;
std::string lookupNatSpecUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionData);
NatSpecFace* natSpec() { return &m_natSpecDB; }
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
QVariant evalRaw(QString const& _js);
QString pretty(dev::Address _a) const override;
QString prettyU256(dev::u256 _n) const override;
QString render(dev::Address _a) const override;
dev::Address fromString(QString const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override;
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
dev::u256 gasPrice() const { return 10 * dev::eth::szabo; }
public slots:
void load(QString _file);
void note(QString _entry);
@ -99,75 +93,80 @@ public slots:
void warn(QString _entry);
QString contents(QString _file);
int authenticate(QString _title, QString _text);
void onKeysChanged();
private slots:
void eval(QString const& _js);
// Application
void on_about_triggered();
void on_quit_triggered() { close(); }
// Network
void on_go_triggered();
void on_net_triggered();
void on_connect_triggered();
void on_idealPeers_valueChanged();
// Mining
void on_mine_triggered();
void on_send_clicked();
void on_create_triggered();
// View
void on_refresh_triggered();
void on_showAll_triggered() { refreshBlockChain(); }
void on_showAllAccounts_triggered() { refreshAccounts(); }
void on_preview_triggered();
// Account management
void on_newAccount_triggered();
void on_killAccount_triggered();
void on_net_triggered();
void on_verbosity_valueChanged();
void on_ourAccounts_doubleClicked();
void on_importKey_triggered();
void on_importKeyFile_triggered();
void on_exportKey_triggered();
// Tools
void on_newTransaction_triggered();
void on_loadJS_triggered();
// Stuff concerning the blocks/transactions/accounts panels
void ourAccountsRowsMoved();
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_destination_currentTextChanged();
void on_data_textChanged();
void on_idealPeers_valueChanged();
void on_value_valueChanged() { updateFee(); }
void on_gas_valueChanged() { updateFee(); }
void on_valueUnits_currentIndexChanged() { updateFee(); }
void on_gasPriceUnits_currentIndexChanged() { updateFee(); }
void on_gasPrice_valueChanged() { updateFee(); }
void on_log_doubleClicked();
void on_blocks_currentItemChanged();
void on_contracts_doubleClicked();
void on_contracts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_about_triggered();
void on_paranoia_triggered();
void on_nameReg_textChanged();
void on_preview_triggered();
void on_quit_triggered() { close(); }
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();
// Logging
void on_log_doubleClicked();
void on_verbosity_valueChanged();
// Misc
void on_urlEdit_returnPressed();
void on_debugStep_triggered();
void on_debugStepBack_triggered();
void on_debug_clicked();
void on_debugTimeline_valueChanged();
void on_jsInput_returnPressed();
void on_nameReg_textChanged();
// Special (debug) stuff
void on_paranoia_triggered();
void on_killBlockchain_triggered();
void on_clearPending_triggered();
void on_importKey_triggered();
void on_exportKey_triggered();
void on_inject_triggered();
void on_showAll_triggered() { refreshBlockChain(); }
void on_showAllAccounts_triggered() { refreshAccounts(); }
void on_loadJS_triggered();
void on_blockChainFilter_textChanged();
void on_forceMining_triggered();
void on_dumpTrace_triggered();
void on_dumpTraceStorage_triggered();
void on_dumpTracePretty_triggered();
void on_debugStepInto_triggered();
void on_debugStepOut_triggered();
void on_debugStepBackOut_triggered();
void on_debugStepBackInto_triggered();
void on_callStack_currentItemChanged();
void on_usePrivate_triggered();
void on_turboMining_triggered();
void on_jitvm_triggered();
// Debugger
void on_debugCurrent_triggered();
void on_debugDumpState_triggered(int _add = 1);
void on_debugDumpStatePre_triggered();
void on_refresh_triggered();
void on_usePrivate_triggered();
void on_enableOptimizer_triggered();
void on_turboMining_triggered();
void on_go_triggered();
void on_importKeyFile_triggered();
void on_post_clicked();
// Whisper
void on_newIdentity_triggered();
void on_jitvm_triggered();
void on_post_clicked();
void refreshWhisper();
void refreshBlockChain();
@ -179,33 +178,14 @@ signals:
private:
dev::p2p::NetworkPreferences netPrefs() const;
QString pretty(dev::Address _a) const;
QString prettyU256(dev::u256 _n) const;
QString lookup(QString const& _n) const;
dev::Address getNameReg() const;
dev::Address getCurrencies() const;
void populateDebugger(dev::bytesConstRef r);
void initDebugger();
void updateDebugger();
void debugFinished();
QString render(dev::Address _a) const;
dev::Address fromString(QString const& _a) const;
std::string renderDiff(dev::eth::StateDiff const& _d) const;
void alterDebugStateGroup(bool _enable) const;
void updateFee();
void readSettings(bool _skipGeometry = false);
void writeSettings();
bool isCreation() const;
dev::u256 fee() const;
dev::u256 total() const;
dev::u256 value() const;
dev::u256 gasPrice() const;
unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f);
unsigned installWatch(dev::h256 _tf, WatchHandler const& _f);
void uninstallWatch(unsigned _w);
@ -232,16 +212,9 @@ private:
void refreshAll();
void refreshPending();
void refreshAccounts();
void refreshDestination();
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;
@ -256,22 +229,8 @@ private:
QList<dev::KeyPair> m_myKeys;
QList<dev::KeyPair> m_myIdentities;
QString m_privateChain;
dev::bytes m_data;
dev::Address m_nameReg;
unsigned m_backupGas;
dev::eth::State m_executiveState;
std::unique_ptr<dev::eth::Executive> m_currentExecution;
dev::h256 m_lastCode;
dev::h256 m_lastData;
std::vector<WorldState const*> m_lastLevels;
QMap<unsigned, unsigned> m_pcWarp;
QList<WorldState> m_history;
std::map<dev::u256, dev::bytes> m_codes; // and pcWarps
bool m_enableOptimizer = true;
QNetworkAccessManager m_webCtrl;
QList<QPair<QString, QString>> m_consoleHistory;
@ -279,10 +238,11 @@ private:
QString m_logHistory;
bool m_logChanged = true;
std::unique_ptr<QWebThreeConnector> m_qwebConnector;
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
std::unique_ptr<OurWebThreeStubServer> m_server;
QWebThree* m_qweb = nullptr;
static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr);
NatspecHandler m_natspecDB;
NatspecHandler m_natSpecDB;
Transact m_transact;
};

13
alethzero/NatspecHandler.cpp

@ -50,16 +50,15 @@ NatspecHandler::~NatspecHandler()
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()));
m_db->Put(m_writeOptions, _contractHash.ref(), _doc);
cdebug << "Registering NatSpec: " << _contractHash.abridged() << _doc;
}
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);
m_db->Get(m_readOptions, _contractHash.ref(), &ret);
cdebug << "Looking up NatSpec: " << _contractHash.abridged() << ret;
return ret;
}
@ -69,8 +68,8 @@ string NatspecHandler::getUserNotice(string const& json, dev::bytes const& _tran
Json::Value userNotice;
string retStr;
m_reader.parse(json, natspec);
bytes transactionFunctionPart(_transactionData.begin(), _transactionData.begin() + 4);
FixedHash<4> transactionFunctionHash(transactionFunctionPart);
FixedHash<4> transactionFunctionHash((bytesConstRef(&_transactionData).cropped(0, 4).toBytes()));
Json::Value methods = natspec["methods"];
for (Json::ValueIterator it = methods.begin(); it != methods.end(); ++it)

5
alethzero/NatspecHandler.h

@ -28,10 +28,11 @@
#pragma warning(pop)
#include <json/json.h>
#include <libdevcore/FixedHash.h>
#include "Context.h"
namespace ldb = leveldb;
class NatspecHandler
class NatspecHandler: public NatSpecFace
{
public:
NatspecHandler();
@ -40,7 +41,7 @@ class 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;
std::string retrieve(dev::h256 const& _contractHash) const override;
/// Given a json natspec string and the transaction data return the user notice
std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData);

71
alethzero/OurWebThreeStubServer.cpp

@ -46,48 +46,71 @@ string OurWebThreeStubServer::shh_newIdentity()
bool OurWebThreeStubServer::showAuthenticationPopup(string const& _title, string const& _text) const
{
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;
int button;
QMetaObject::invokeMethod(m_main, "authenticate", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, button), Q_ARG(QString, QString::fromStdString(_title)), Q_ARG(QString, QString::fromStdString(_text)));
return button == QMessageBox::Ok;
}
void OurWebThreeStubServer::showBasicValueTransferNotice(u256 _value) const
bool OurWebThreeStubServer::showCreationNotice(TransactionSkeleton const& _t) const
{
QMessageBox notice;
notice.setText("Basic Value Transfer Transaction");
notice.setInformativeText(QString::fromStdString("Value is " + toString(_value)));
notice.setStandardButtons(QMessageBox::Ok);
notice.exec();
return showAuthenticationPopup("Contract Creation Transaction", "ÐApp is attemping to create a contract; to be endowed with " + formatBalance(_t.value) + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is <b>" + formatBalance(_t.value + _t.gas * _t.gasPrice) + "</b>.");
}
bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t) const
{
return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to).toStdString() + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is <b>" + formatBalance(_t.value + _t.gas * _t.gasPrice) + "</b>.");
}
bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t) const
{
return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!",
"ÐApp is attempting to call into an unknown contract at address " +
m_main->pretty(_t.to).toStdString() +
".\n\nCall involves sending " +
formatBalance(_t.value) + " to the recipient, with additional network fees of up to " +
formatBalance(_t.gas * _t.gasPrice) +
"However, this also does other stuff which we don't understand, and does so in your name.\n\n" +
"WARNING: This is probably going to cost you at least " +
formatBalance(_t.value + _t.gas * _t.gasPrice) +
", however this doesn't include any side-effects, which could be of far greater importance.\n\n" +
"REJECT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!");
}
bool OurWebThreeStubServer::authenticate(TransactionSkeleton const& _t)
{
if (_t.creation)
{
// recipient has no code - nothing special about this transaction, show basic value transfer info
return showCreationNotice(_t);
}
h256 contractCodeHash = m_web3->ethereum()->postState().codeHash(_t.to);
if (contractCodeHash == EmptySHA3)
// contract creation
return true;
if (false) //TODO: When is is just a value transfer?
{
// recipient has no code - nothing special about this transaction, show basic value transfer info
showBasicValueTransferNotice(_t.value);
return true;
return showSendNotice(_t);
}
string userNotice = m_main->lookupNatSpecUserNotice(contractCodeHash, _t.data);
string userNotice = m_main->natSpec()->getUserNotice(contractCodeHash, _t.data);
if (userNotice.empty())
return showAuthenticationPopup("Unverified Pending Transaction",
"An undocumented transaction is about to be executed.");
return showUnknownCallNotice(_t);
NatspecExpressionEvaluator evaluator;
userNotice = evaluator.evalExpression(QString::fromStdString(userNotice)).toStdString();
// otherwise it's a transaction to a contract for which we have the natspec
return showAuthenticationPopup("Pending Transaction", userNotice);
return showAuthenticationPopup("Contract Transaction",
"ÐApp attempting to conduct contract interaction with " +
m_main->pretty(_t.to).toStdString() +
": <b>" + userNotice + "</b>.\n\n" +
(_t.value > 0 ?
"In addition, ÐApp is attempting to send " +
formatBalance(_t.value) + " to said recipient, with additional network fees of up to " +
formatBalance(_t.gas * _t.gasPrice) + " = <b>" +
formatBalance(_t.value + _t.gas * _t.gasPrice) + "</b>."
:
"Additional network fees are at most" +
formatBalance(_t.gas * _t.gasPrice) + ".")
);
}

4
alethzero/OurWebThreeStubServer.h

@ -42,7 +42,9 @@ signals:
private:
bool showAuthenticationPopup(std::string const& _title, std::string const& _text) const;
void showBasicValueTransferNotice(dev::u256 _value) const;
bool showCreationNotice(dev::eth::TransactionSkeleton const& _t) const;
bool showSendNotice(dev::eth::TransactionSkeleton const& _t) const;
bool showUnknownCallNotice(dev::eth::TransactionSkeleton const& _t) const;
dev::WebThreeDirect* m_web3;
Main* m_main;

336
alethzero/Transact.cpp

@ -0,0 +1,336 @@
/*
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 Transact.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Transact.h"
#include <fstream>
#include <QFileDialog>
#include <QMessageBox>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/AST.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#ifndef _MSC_VER
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#endif
#include "Debugger.h"
#include "ui_Transact.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
Transact::Transact(Context* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Transact),
m_context(_c)
{
ui->setupUi(this);
initUnits(ui->gasPriceUnits);
initUnits(ui->valueUnits);
ui->valueUnits->setCurrentIndex(6);
ui->gasPriceUnits->setCurrentIndex(4);
ui->gasPrice->setValue(10);
on_destination_currentTextChanged();
}
Transact::~Transact()
{
delete ui;
}
void Transact::setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB)
{
m_myKeys = _myKeys;
m_ethereum = _eth;
m_natSpecDB = _natSpecDB;
}
bool Transact::isCreation() const
{
return ui->destination->currentText().isEmpty() || ui->destination->currentText() == "(Create Contract)";
}
u256 Transact::fee() const
{
return ui->gas->value() * gasPrice();
}
u256 Transact::value() const
{
if (ui->valueUnits->currentIndex() == -1)
return 0;
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first;
}
u256 Transact::gasPrice() const
{
if (ui->gasPriceUnits->currentIndex() == -1)
return 0;
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first;
}
u256 Transact::total() const
{
return value() + fee();
}
void Transact::updateDestination()
{
cwatch << "updateDestination()";
QString s;
for (auto i: ethereum()->addresses())
if ((s = m_context->pretty(i)).size())
// A namereg address
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)))
ui->destination->removeItem(i--);
}
void Transact::updateFee()
{
ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str()));
auto totalReq = total();
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str()));
bool ok = false;
for (auto i: m_myKeys)
if (ethereum()->balanceAt(i.address()) >= totalReq)
{
ok = true;
break;
}
ui->send->setEnabled(ok);
QPalette p = ui->total->palette();
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00));
ui->total->setPalette(p);
}
string Transact::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->getDeclaration().getName() + "\n";
}
return ret;
}
void Transact::on_destination_currentTextChanged()
{
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
if (Address a = m_context->fromString(ui->destination->currentText()))
ui->calculatedName->setText(m_context->render(a));
else
ui->calculatedName->setText("Unknown Address");
else
ui->calculatedName->setText("Create Contract");
rejigData();
// updateFee();
}
void Transact::rejigData()
{
if (isCreation())
{
string src = ui->data->toPlainText().toStdString();
vector<string> errors;
QString lll;
QString solidity;
if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0)
{
m_data = fromHex(src);
}
else if (sourceIsSolidity(src))
{
dev::solidity::CompilerStack compiler;
try
{
// compiler.addSources(dev::solidity::StandardSources);
m_data = compiler.compile(src, ui->optimize->isChecked());
solidity = "<h4>Solidity</h4>";
solidity += "<pre>var " + QString::fromStdString(compiler.defaultContractName()) + " = web3.eth.contractFromAbi(" + 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)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>";
}
catch (...)
{
solidity = "<h4>Solidity</h4><pre>Uncaught exception.</pre>";
}
}
#ifndef _MSC_VER
else if (sourceIsSerpent(src))
{
try
{
m_data = dev::asBytes(::compile(src));
for (auto& i: errors)
i = "(LLL " + i + ")";
}
catch (string err)
{
errors.push_back("Serpent " + err);
}
}
#endif
else
{
m_data = compileLLL(src, ui->optimize->isChecked(), &errors);
if (errors.empty())
{
auto asmcode = compileLLLToAsm(src, false);
lll = "<h4>Pre</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>";
if (ui->optimize->isChecked())
{
asmcode = compileLLLToAsm(src, true);
lll = "<h4>Opt</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>" + lll;
}
}
}
QString errs;
if (errors.size())
{
errs = "<h4>Errors</h4>";
for (auto const& i: errors)
errs.append("<div style=\"border-left: 6px solid #c00; margin-top: 2px\">" + QString::fromStdString(i).toHtmlEscaped() + "</div>");
}
ui->code->setHtml(errs + lll + solidity + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped() + "<h4>Hex</h4>" Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>");
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 0));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
}
else
{
m_data = parseData(ui->data->toPlainText().toStdString());
auto to = m_context->fromString(ui->destination->currentText());
QString natspec;
if (ethereum()->codeAt(to, 0).size())
{
string userNotice = m_natSpecDB->getUserNotice(ethereum()->postState().codeHash(to), m_data);
if (userNotice.empty())
natspec = "Destination contract unknown.";
else
{
NatspecExpressionEvaluator evaluator;
natspec = evaluator.evalExpression(QString::fromStdString(userNotice));
}
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 1));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
}
else
{
natspec += "Destination not a contract.";
if (ui->gas->isEnabled())
m_backupGas = ui->gas->value();
ui->gas->setValue((qint64)Interface::txGas(m_data));
ui->gas->setEnabled(false);
}
ui->code->setHtml("<h3>NatSpec</h3>" + natspec + "<h3>Dump</h3>" + QString::fromStdString(dev::memDump(m_data, 8, true)) + "<h3>Hex</h3>" + Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>");
}
updateFee();
}
void Transact::on_send_clicked()
{
u256 totalReq = value() + fee();
for (auto const& i: m_myKeys)
if (ethereum()->balanceAt(i.address(), 0) >= totalReq)
{
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, ui->optimize->isChecked());
for (string const& s: compiler.getContractNames())
{
h256 contractHash = compiler.getContractCodeHash(s);
m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser));
}
}
catch (...)
{
}
close();
return;
}
else
ethereum()->transact(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
return;
}
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
}
void Transact::on_debug_clicked()
{
try
{
u256 totalReq = value() + fee();
for (auto i: m_myKeys)
if (ethereum()->balanceAt(i.address()) >= totalReq)
{
State st(ethereum()->postState());
Secret s = i.secret();
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s);
Debugger dw(m_context, this);
Executive e(st, ethereum()->blockChain(), 0);
dw.populate(e, t);
dw.exec();
return;
}
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
}
catch (dev::Exception const& _e)
{
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction. Low-level error: " + QString::fromStdString(diagnostic_information(_e)));
// this output is aimed at developers, reconsider using _e.what for more user friendly output.
}
}

82
alethzero/Transact.h

@ -0,0 +1,82 @@
/*
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 Transact.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h>
#include <libethereum/Transaction.h>
#include <QDialog>
#include <QMap>
#include <QList>
#include "Context.h"
namespace Ui { class Transact; }
namespace dev { namespace eth { class Client; } }
namespace dev { namespace solidity { class CompilerStack; } }
class Transact: public QDialog
{
Q_OBJECT
public:
explicit Transact(Context* _context, QWidget* _parent = 0);
~Transact();
void setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB);
private slots:
void on_destination_currentTextChanged();
void on_value_valueChanged() { updateFee(); }
void on_gas_valueChanged() { updateFee(); }
void on_valueUnits_currentIndexChanged() { updateFee(); }
void on_gasPriceUnits_currentIndexChanged() { updateFee(); }
void on_gasPrice_valueChanged() { updateFee(); }
void on_data_textChanged() { rejigData(); }
void on_optimize_clicked() { rejigData(); }
void on_send_clicked();
void on_debug_clicked();
void on_cancel_clicked() { close(); }
private:
dev::eth::Client* ethereum() { return m_ethereum; }
void rejigData();
void updateDestination();
void updateFee();
bool isCreation() const;
dev::u256 fee() const;
dev::u256 total() const;
dev::u256 value() const;
dev::u256 gasPrice() const;
std::string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, std::string const& _contractName = std::string());
Ui::Transact* ui;
unsigned m_backupGas;
dev::bytes m_data;
QList<dev::KeyPair> m_myKeys;
dev::eth::Client* m_ethereum;
Context* m_context;
NatSpecFace* m_natSpecDB;
};

244
alethzero/Transact.ui

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Transact</class>
<widget class="QDialog" name="Transact">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>543</width>
<height>695</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Amount</string>
</property>
<property name="buddy">
<cstring>value</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="4" column="1" colspan="2">
<widget class="QLabel" name="fee">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="7" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>&amp;Debug</string>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QPushButton" name="send">
<property name="text">
<string>&amp;Execute</string>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property>
<property name="buddy">
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="gas">
<property name="suffix">
<string> gas</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>D&amp;ata</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="destination">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>(Create Contract)</string>
</property>
</item>
</widget>
</item>
<item row="6" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

3
cmake/EthCompilerSettings.cmake

@ -27,13 +27,14 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# enable parallel compilation
# specify Exception Handling Model in msvc
# disable unknown pragma warning (4068)
# disable unsafe function warning (4996)
# disable decorated name length exceeded, name was truncated (4503)
# disable warning C4535: calling _set_se_translator() requires /EHa (for boost tests)
# declare Windows XP requirement
add_compile_options(/EHsc /wd4068 /wd4996 /wd4503 -D_WIN32_WINNT=0x0501)
add_compile_options(/MP /EHsc /wd4068 /wd4996 /wd4503 -D_WIN32_WINNT=0x0501)
# disable empty object file warning
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
# warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification

4
cmake/EthDependencies.cmake

@ -59,6 +59,10 @@ if (JSONRPC)
message (" - json-rpc-cpp lib : ${JSON_RPC_CPP_LIBRARIES}")
add_definitions(-DETH_JSONRPC)
find_package(MHD)
message(" - microhttpd header: ${MHD_INCLUDE_DIRS}")
message(" - microhttpd lib : ${MHD_LIBRARIES}")
endif() #JSONRPC
# TODO readline package does not yet check for correct version number

47
cmake/FindMHD.cmake

@ -0,0 +1,47 @@
# Find microhttpd
#
# Find the microhttpd includes and library
#
# if you need to add a custom library search path, do it via via CMAKE_PREFIX_PATH
#
# This module defines
# MHD_INCLUDE_DIRS, where to find header, etc.
# MHD_LIBRARIES, the libraries needed to use jsoncpp.
# MHD_FOUND, If false, do not try to use jsoncpp.
find_path(
MHD_INCLUDE_DIR
NAMES microhttpd.h
DOC "microhttpd include dir"
)
find_library(
MHD_LIBRARY
NAMES microhttpd microhttpd-10 libmicrohttpd libmicrohttpd-dll
DOC "microhttpd library"
)
set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR})
set(MHD_LIBRARIES ${MHD_LIBRARY})
# debug library on windows
# same naming convention as in QT (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
# official MHD project actually uses _d suffix
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library(
MHD_LIBRARY_DEBUG
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d
DOC "mhd debug library"
)
set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(mhd DEFAULT_MSG
MHD_INCLUDE_DIR MHD_LIBRARY)
mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY)

8
extdep/CMakeLists.txt

@ -35,14 +35,18 @@ if (ETH_COMPILE)
include(compile/boost.cmake)
else()
eth_download(jsoncpp)
eth_download(json-rpc-cpp OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh)
eth_download(microhttpd)
eth_download(json-rpc-cpp
VERSION 4.2
OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh
)
if (APPLE)
eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh)
endif()
eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh)
eth_download(qt)
eth_download(qt VERSION 5.4)
eth_download(cryptopp)
eth_download(boost)
eth_download(curl)

5
libdevcore/vector_ref.h

@ -1,7 +1,8 @@
#pragma once
#include <type_traits>
#include <cstring>
#include <cassert>
#include <type_traits>
#include <vector>
#include <string>
@ -18,7 +19,7 @@ public:
vector_ref(): m_data(nullptr), m_count(0) {}
vector_ref(_T* _data, size_t _count): m_data(_data), m_count(_count) {}
vector_ref(std::string* _data): m_data((_T*)_data->data()), m_count(_data->size() / sizeof(_T)) {}
vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const*, std::string*>::type _data): m_data((_T*)_data->data()), m_count(_data->size() / sizeof(_T)) {}
vector_ref(typename std::conditional<std::is_const<_T>::value, std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data): m_data(_data->data()), m_count(_data->size()) {}
vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type _data): m_data((_T*)_data.data()), m_count(_data.size() / sizeof(_T)) {}
#ifdef STORAGE_LEVELDB_INCLUDE_DB_H_

10
libethcore/CommonEth.cpp

@ -35,16 +35,6 @@ namespace eth
const unsigned c_protocolVersion = 53;
const unsigned c_databaseVersion = 5;
template <size_t n> u256 exp10()
{
return exp10<n - 1>() * u256(10);
}
template <> u256 exp10<0>()
{
return u256(1);
}
vector<pair<u256, string>> const& units()
{
static const vector<pair<u256, string>> s_units =

33
libethcore/CommonEth.h

@ -47,26 +47,21 @@ std::vector<std::pair<u256, std::string>> const& units();
/// The log bloom's size (512 bit).
using LogBloom = h512;
template <size_t n> inline u256 exp10()
{
return exp10<n - 1>() * u256(10);
}
template <> inline u256 exp10<0>()
{
return u256(1);
}
// The various denominations; here for ease of use where needed within code.
/*static const u256 Uether = ((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000;
static const u256 Vether = ((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000;
static const u256 Dether = ((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000;
static const u256 Nether = (((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000;
static const u256 Yether = (((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000;
static const u256 Zether = (((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000;
static const u256 Eether = ((u256(1000000000) * 1000000000) * 1000000000) * 1000000000;
static const u256 Pether = ((u256(1000000000) * 1000000000) * 1000000000) * 1000000;
static const u256 Tether = ((u256(1000000000) * 1000000000) * 1000000000) * 1000;
static const u256 Gether = (u256(1000000000) * 1000000000) * 1000000000;
static const u256 Mether = (u256(1000000000) * 1000000000) * 1000000;
static const u256 grand = (u256(1000000000) * 1000000000) * 1000;*/
static const u256 ether = u256(1000000000) * 1000000000;
static const u256 finney = u256(1000000000) * 1000000;
static const u256 szabo = u256(1000000000) * 1000;
/*static const u256 Gwei = u256(1000000000);
static const u256 Mwei = u256(1000000);
static const u256 Kwei = u256(1000);*/
static const u256 wei = u256(1);
static const u256 ether = exp10<18>();
static const u256 finney = exp10<15>();
static const u256 szabo = exp10<12>();
static const u256 wei = exp10<0>();
}
}

13
libethcore/CommonJS.cpp

@ -97,7 +97,7 @@ std::string fromRaw(h256 _n, unsigned* _inc)
return "";
}
std::string prettyU256(u256 _n)
std::string prettyU256(u256 _n, bool _abridged)
{
unsigned inc = 0;
std::string raw;
@ -110,11 +110,16 @@ std::string prettyU256(u256 _n)
{
Address a = right160(_n);
std::string n = a.abridged();
std::string n;
if (_abridged)
n = a.abridged();
else
n = toHex(a.ref());
if (n.empty())
s << "0x" << a;
s << "0";
else
s << n << "(0x" << a.abridged() << ")";
s << _n << "(0x" << n << ")";
}
else if ((raw = fromRaw((h256)_n, &inc)).size())
return "\"" + raw + "\"" + (inc ? " + " + std::to_string(inc) : "");

3
libethcore/CommonJS.h

@ -59,7 +59,7 @@ bytes unpadded(bytes _s);
/// Remove all 0 byte on the head of @a _s.
bytes unpadLeft(bytes _s);
/// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256.
std::string prettyU256(u256 _n);
std::string prettyU256(u256 _n, bool _abridged = true);
/// Convert h256 into user-readable string (by directly using std::string constructor).
std::string fromRaw(h256 _n, unsigned* _inc = nullptr);
/// Convert string to Address (h160), returns empty address if (_a.size != 40).
@ -144,6 +144,7 @@ inline Address jsToAddress(std::string const& _s) { return jsToFixed<sizeof(dev:
struct TransactionSkeleton
{
bool creation = false;
Address from;
Address to;
u256 value;

4
libethereum/BlockChain.h

@ -112,6 +112,10 @@ public:
bytes block(h256 _hash) const;
bytes block() const { return block(currentHash()); }
/// Get a block's transaction (RLP format) for the given block hash (or the most recent mined if none given) & index. Thread-safe.
bytes transaction(h256 _hash, unsigned _i) const { bytes b = block(_hash); return RLP(b)[1][_i].data().toBytes(); }
bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); }
/// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
unsigned number(h256 _hash) const { return details(_hash).number; }
unsigned number() const { return number(currentHash()); }

6
libethereum/Executive.cpp

@ -54,6 +54,12 @@ bool Executive::setup(bytesConstRef _rlp)
{
// Entry point for a user-executed transaction.
m_t = Transaction(_rlp, CheckSignature::Sender);
return setup();
}
bool Executive::setup()
{
// Entry point for a user-executed transaction.
// Avoid invalid transactions.
auto nonceReq = m_s.transactionsFrom(m_t.sender());

5
libethereum/Executive.h

@ -62,6 +62,9 @@ public:
/// Set up the executive for evaluating a transaction. You must call finalize() following this.
/// @returns true iff go() must be called (and thus a VM execution in required).
bool setup(bytesConstRef _transaction);
/// Set up the executive for evaluating a transaction. You must call finalize() following this.
/// @returns true iff go() must be called (and thus a VM execution in required).
bool setup(Transaction const& _transaction) { m_t = _transaction; return setup(); }
/// Finalise a transaction previously set up with setup().
/// @warning Only valid after setup(), and possibly go().
void finalize();
@ -101,6 +104,8 @@ public:
bool excepted() const { return m_excepted; }
private:
bool setup();
State& m_s; ///< The state to which this operation/transaction is applied.
LastHashes m_lastHashes;
std::shared_ptr<ExtVM> m_ext; ///< The VM externality object for the VM execution or null if no VM is required.

4
libjsqrc/setup.js

@ -20,8 +20,6 @@
* @date 2014
*/
navigator.qt = _web3;
var web3 = require('web3');
web3.setProvider(new web3.providers.QtSyncProvider());
web3.setProvider(new web3.providers.HttpSyncProvider());

6
libp2p/NodeTable.h

@ -168,10 +168,10 @@ public:
/// Returns the Node to the corresponding node id or the empty Node if that id is not found.
Node node(NodeId const& _id);
#ifndef BOOST_AUTO_TEST_SUITE
private:
#else
#if defined(BOOST_AUTO_TEST_SUITE) || defined(_MSC_VER) // MSVC includes access specifier in symbol name
protected:
#else
private:
#endif
/// Constants for Kademlia, derived from address space.

41
libqwebthree/CMakeLists.txt

@ -1,41 +0,0 @@
cmake_policy(SET CMP0015 NEW)
# let cmake autolink dependencies on windows
cmake_policy(SET CMP0020 NEW)
# this policy was introduced in cmake 3.0
# remove if, once 3.0 will be used on unix
if (${CMAKE_MAJOR_VERSION} GREATER 2)
# old policy do not use MACOSX_RPATH
cmake_policy(SET CMP0042 OLD)
cmake_policy(SET CMP0043 OLD)
endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(..)
set(EXECUTABLE qwebthree)
file(GLOB HEADERS "*.h")
if(ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Gui)
target_link_libraries(${EXECUTABLE} Qt5::WebKit)
target_link_libraries(${EXECUTABLE} Qt5::WebKitWidgets)
target_link_libraries(${EXECUTABLE} Qt5::Widgets)
target_link_libraries(${EXECUTABLE} Qt5::Network)
target_link_libraries(${EXECUTABLE} Qt5::Quick)
target_link_libraries(${EXECUTABLE} Qt5::Qml)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES})
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} secp256k1)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

107
libqwebthree/QWebThree.cpp

@ -1,107 +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 QWebThree.cpp
* @authors:
* Gav Wood <i@gavwood.com>
* Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
#include <QtCore/QtCore>
#include "QWebThree.h"
using namespace std;
QWebThree::QWebThree(QObject* _p): QObject(_p)
{
moveToThread(_p->thread());
}
QWebThree::~QWebThree()
{
clientDieing();
}
void QWebThree::clientDieing()
{
this->disconnect();
}
QString QWebThree::callMethod(QString _json)
{
emit processData(_json, ""); // it's synchronous
return m_response;
}
void QWebThree::onDataProcessed(QString _json, QString)
{
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
syncResponse(QString::fromUtf8(QJsonDocument(f).toJson()));
}
void QWebThree::syncResponse(QString _json)
{
m_response = _json;
}
QWebThreeConnector::QWebThreeConnector()
{
}
QWebThreeConnector::~QWebThreeConnector()
{
StopListening();
}
void QWebThreeConnector::setQWeb(QWebThree* _q)
{
m_qweb = _q;
if (m_isListening)
{
StopListening();
StartListening();
}
}
bool QWebThreeConnector::StartListening()
{
m_isListening = true;
if (m_qweb)
{
connect(m_qweb, SIGNAL(processData(QString, QString)), this, SLOT(onProcessData(QString, QString)));
connect(this, SIGNAL(dataProcessed(QString, QString)), m_qweb, SLOT(onDataProcessed(QString, QString)));
}
return true;
}
bool QWebThreeConnector::StopListening()
{
this->disconnect();
return true;
}
bool QWebThreeConnector::SendResponse(std::string const& _response, void* _addInfo)
{
emit dataProcessed(QString::fromStdString(_response), *(QString*)_addInfo);
return true;
}
void QWebThreeConnector::onProcessData(QString const& _json, QString const& _addInfo)
{
OnRequest(_json.toStdString(), (void*)&_addInfo);
}

89
libqwebthree/QWebThree.h

@ -1,89 +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 QWebThree.h
* @authors:
* Gav Wood <i@gavwood.com>
* Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
#pragma once
#include <QtCore/QObject>
#include <QtCore/QString>
#include <jsonrpccpp/server.h>
class QWebThree: public QObject
{
Q_OBJECT
public:
QWebThree(QObject* _p);
virtual ~QWebThree();
void clientDieing();
Q_INVOKABLE QString callMethod(QString _json);
void syncResponse(QString _json);
public slots:
void onDataProcessed(QString _json, QString _addInfo);
signals:
void processData(QString _json, QString _addInfo);
void response(QString _json);
void onNewId(QString _id);
private:
QString m_response;
};
class QWebThreeConnector: public QObject, public jsonrpc::AbstractServerConnector
{
Q_OBJECT
public:
QWebThreeConnector();
virtual ~QWebThreeConnector();
void setQWeb(QWebThree *_q);
virtual bool StartListening();
virtual bool StopListening();
virtual bool SendResponse(std::string const& _response, void* _addInfo = NULL);
public slots:
void onProcessData(QString const& _json, QString const& _addInfo);
signals:
void dataProcessed(QString const& _json, QString const& _addInfo);
private:
QWebThree* m_qweb = nullptr;
bool m_isListening;
};
#define QETH_INSTALL_JS_NAMESPACE(_frame, _env, qweb) [_frame, _env, qweb]() \
{ \
_frame->disconnect(); \
_frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \
_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/bignumber.min.js")); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/webthree.js")); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/setup.js")); \
}

12
libsolidity/AST.cpp

@ -206,6 +206,13 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn
return *m_interfaceFunctionList;
}
TypePointer EnumValue::getType(ContractDefinition const*) const
{
EnumDefinition const* parentDef = dynamic_cast<EnumDefinition const*>(getScope());
solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
return make_shared<EnumType>(*parentDef);
}
void InheritanceSpecifier::checkTypeRequirements()
{
m_baseName->checkTypeRequirements();
@ -255,6 +262,11 @@ void StructDefinition::checkRecursion() const
}
}
TypePointer EnumDefinition::getType(ContractDefinition const*) const
{
return make_shared<TypeType>(make_shared<EnumType>(*this));
}
TypePointer FunctionDefinition::getType(ContractDefinition const*) const
{
return make_shared<FunctionType>(*this);

39
libsolidity/AST.h

@ -209,6 +209,7 @@ public:
ASTPointer<ASTString> const& _documentation,
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
@ -216,6 +217,7 @@ public:
Declaration(_location, _name), Documented(_documentation),
m_baseContracts(_baseContracts),
m_definedStructs(_definedStructs),
m_definedEnums(_definedEnums),
m_stateVariables(_stateVariables),
m_definedFunctions(_definedFunctions),
m_functionModifiers(_functionModifiers),
@ -227,6 +229,7 @@ public:
std::vector<ASTPointer<InheritanceSpecifier>> const& getBaseContracts() const { return m_baseContracts; }
std::vector<ASTPointer<StructDefinition>> const& getDefinedStructs() const { return m_definedStructs; }
std::vector<ASTPointer<EnumDefinition>> const& getDefinedEnums() const { return m_definedEnums; }
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
@ -260,6 +263,7 @@ private:
std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts;
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
std::vector<ASTPointer<EnumDefinition>> m_definedEnums;
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;
std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions;
std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers;
@ -315,6 +319,39 @@ private:
std::vector<ASTPointer<VariableDeclaration>> m_members;
};
class EnumDefinition: public Declaration
{
public:
EnumDefinition(Location const& _location,
ASTPointer<ASTString> const& _name,
std::vector<ASTPointer<EnumValue>> const& _members):
Declaration(_location, _name), m_members(_members) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
std::vector<ASTPointer<EnumValue>> const& getMembers() const { return m_members; }
virtual TypePointer getType(ContractDefinition const*) const override;
private:
std::vector<ASTPointer<EnumValue>> m_members;
};
/**
* Declaration of an Enum Value
*/
class EnumValue: public Declaration
{
public:
EnumValue(Location const& _location,
ASTPointer<ASTString> const& _name):
Declaration(_location, _name) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
TypePointer getType(ContractDefinition const* = nullptr) const;
};
/**
* Parameter list, used as function parameter list and return list.
* None of the parameters is allowed to contain mappings (not even recursively
@ -679,7 +716,7 @@ public:
Expression const& getCondition() const { return *m_condition; }
Statement const& getTrueStatement() const { return *m_trueBody; }
/// @returns the "else" part of the if statement or nullptr if there is no "else" part.
/// @returns the "else" part of the if statement or nullptr if there is no "else" part.
Statement const* getFalseStatement() const { return m_falseBody.get(); }
private:

2
libsolidity/ASTForward.h

@ -40,6 +40,8 @@ class Declaration;
class ContractDefinition;
class InheritanceSpecifier;
class StructDefinition;
class EnumDefinition;
class EnumValue;
class ParameterList;
class FunctionDefinition;
class VariableDeclaration;

22
libsolidity/ASTPrinter.cpp

@ -71,6 +71,18 @@ bool ASTPrinter::visit(StructDefinition const& _node)
return goDeeper();
}
bool ASTPrinter::visit(EnumDefinition const& _node)
{
writeLine("EnumDefinition \"" + _node.getName() + "\"");
return goDeeper();
}
bool ASTPrinter::visit(EnumValue const& _node)
{
writeLine("EnumValue \"" + _node.getName() + "\"");
return goDeeper();
}
bool ASTPrinter::visit(ParameterList const& _node)
{
writeLine("ParameterList");
@ -347,6 +359,16 @@ void ASTPrinter::endVisit(StructDefinition const&)
m_indentation--;
}
void ASTPrinter::endVisit(EnumDefinition const&)
{
m_indentation--;
}
void ASTPrinter::endVisit(EnumValue const&)
{
m_indentation--;
}
void ASTPrinter::endVisit(ParameterList const&)
{
m_indentation--;

4
libsolidity/ASTPrinter.h

@ -46,6 +46,8 @@ public:
bool visit(ContractDefinition const& _node) override;
bool visit(InheritanceSpecifier const& _node) override;
bool visit(StructDefinition const& _node) override;
bool visit(EnumDefinition const& _node) override;
bool visit(EnumValue const& _node) override;
bool visit(ParameterList const& _node) override;
bool visit(FunctionDefinition const& _node) override;
bool visit(VariableDeclaration const& _node) override;
@ -85,6 +87,8 @@ public:
void endVisit(ContractDefinition const&) override;
void endVisit(InheritanceSpecifier const&) override;
void endVisit(StructDefinition const&) override;
void endVisit(EnumDefinition const&) override;
void endVisit(EnumValue const&) override;
void endVisit(ParameterList const&) override;
void endVisit(FunctionDefinition const&) override;
void endVisit(VariableDeclaration const&) override;

8
libsolidity/ASTVisitor.h

@ -47,6 +47,8 @@ public:
virtual bool visit(ContractDefinition&) { return true; }
virtual bool visit(InheritanceSpecifier&) { return true; }
virtual bool visit(StructDefinition&) { return true; }
virtual bool visit(EnumDefinition&) { return true; }
virtual bool visit(EnumValue&) { return true; }
virtual bool visit(ParameterList&) { return true; }
virtual bool visit(FunctionDefinition&) { return true; }
virtual bool visit(VariableDeclaration&) { return true; }
@ -88,6 +90,8 @@ public:
virtual void endVisit(ContractDefinition&) { }
virtual void endVisit(InheritanceSpecifier&) { }
virtual void endVisit(StructDefinition&) { }
virtual void endVisit(EnumDefinition&) { }
virtual void endVisit(EnumValue&) { }
virtual void endVisit(ParameterList&) { }
virtual void endVisit(FunctionDefinition&) { }
virtual void endVisit(VariableDeclaration&) { }
@ -133,6 +137,8 @@ public:
virtual bool visit(ContractDefinition const&) { return true; }
virtual bool visit(InheritanceSpecifier const&) { return true; }
virtual bool visit(StructDefinition const&) { return true; }
virtual bool visit(EnumDefinition const&) { return true; }
virtual bool visit(EnumValue const&) { return true; }
virtual bool visit(ParameterList const&) { return true; }
virtual bool visit(FunctionDefinition const&) { return true; }
virtual bool visit(VariableDeclaration const&) { return true; }
@ -174,6 +180,8 @@ public:
virtual void endVisit(ContractDefinition const&) { }
virtual void endVisit(InheritanceSpecifier const&) { }
virtual void endVisit(StructDefinition const&) { }
virtual void endVisit(EnumDefinition const&) { }
virtual void endVisit(EnumValue const&) { }
virtual void endVisit(ParameterList const&) { }
virtual void endVisit(FunctionDefinition const&) { }
virtual void endVisit(VariableDeclaration const&) { }

28
libsolidity/AST_accept.h

@ -63,6 +63,7 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
{
listAccept(m_baseContracts, _visitor);
listAccept(m_definedStructs, _visitor);
listAccept(m_definedEnums, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_events, _visitor);
listAccept(m_functionModifiers, _visitor);
@ -77,6 +78,7 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const
{
listAccept(m_baseContracts, _visitor);
listAccept(m_definedStructs, _visitor);
listAccept(m_definedEnums, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_events, _visitor);
listAccept(m_functionModifiers, _visitor);
@ -105,6 +107,32 @@ void InheritanceSpecifier::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
void EnumDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
listAccept(m_members, _visitor);
_visitor.endVisit(*this);
}
void EnumDefinition::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
listAccept(m_members, _visitor);
_visitor.endVisit(*this);
}
void EnumValue::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void EnumValue::accept(ASTConstVisitor& _visitor) const
{
_visitor.visit(*this);
_visitor.endVisit(*this);
}
void StructDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))

5
libsolidity/CompilerStack.cpp

@ -333,6 +333,11 @@ void CompilerStack::resolveImports()
swap(m_sourceOrder, sourceOrder);
}
std::string CompilerStack::defaultContractName() const
{
return getContract("").contract->getName();
}
CompilerStack::Contract const& CompilerStack::getContract(string const& _contractName) const
{
if (m_contracts.empty())

1
libsolidity/CompilerStack.h

@ -73,6 +73,7 @@ public:
void parse(std::string const& _sourceCode);
/// Returns a list of the contract names in the sources.
std::vector<std::string> getContractNames() const;
std::string defaultContractName() const;
/// Compiles the source units that were previously added and parsed.
void compile(bool _optimize = false);

28
libsolidity/ExpressionCompiler.cpp

@ -489,13 +489,21 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
break;
}
case Type::Category::Enum:
{
EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.getExpression().getType());
m_context << type.getMemberValue(_memberAccess.getMemberName());
break;
}
case Type::Category::TypeType:
{
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType());
if (type.getMembers().getMemberType(member))
if (!type.getMembers().getMemberType(member))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
if (auto contractType = dynamic_cast<ContractType const*>(type.getActualType().get()))
{
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*type.getActualType())
.getContractDefinition();
ContractDefinition const& contract = contractType->getContractDefinition();
for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions())
if (function->getName() == member)
{
@ -503,7 +511,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
return;
}
}
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
else if (auto enumType = dynamic_cast<EnumType const*>(type.getActualType().get()))
m_context << enumType->getMemberValue(_memberAccess.getMemberName());
break;
}
case Type::Category::ByteArray:
{
@ -562,6 +572,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
{
// no-op
}
else if (dynamic_cast<EnumDefinition const*>(declaration))
{
// no-op
}
else
{
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
@ -745,6 +759,9 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
}
}
}
else if (stackTypeCategory == Type::Category::Enum)
solAssert(targetTypeCategory == Type::Category::Integer ||
targetTypeCategory == Type::Category::Enum, "");
else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract ||
stackTypeCategory == Type::Category::IntegerConstant)
{
@ -758,6 +775,9 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL;
}
else if (targetTypeCategory == Type::Category::Enum)
// just clean
appendTypeConversion(_typeOnStack, *_typeOnStack.getRealType(), true);
else
{
solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, "");

19
libsolidity/NameAndTypeResolver.cpp

@ -58,6 +58,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
for (ASTPointer<EnumDefinition> const& enumDef: _contract.getDefinedEnums())
ReferencesResolver resolver(*enumDef, *this, &_contract, nullptr);
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
for (ASTPointer<EventDefinition> const& event: _contract.getEvents())
@ -221,6 +223,23 @@ void DeclarationRegistrationHelper::endVisit(StructDefinition&)
closeCurrentScope();
}
bool DeclarationRegistrationHelper::visit(EnumDefinition& _enum)
{
registerDeclaration(_enum, true);
return true;
}
void DeclarationRegistrationHelper::endVisit(EnumDefinition&)
{
closeCurrentScope();
}
bool DeclarationRegistrationHelper::visit(EnumValue& _value)
{
registerDeclaration(_value, false);
return true;
}
bool DeclarationRegistrationHelper::visit(FunctionDefinition& _function)
{
registerDeclaration(_function, true);

3
libsolidity/NameAndTypeResolver.h

@ -98,6 +98,9 @@ private:
void endVisit(ContractDefinition& _contract) override;
bool visit(StructDefinition& _struct) override;
void endVisit(StructDefinition& _struct) override;
bool visit(EnumDefinition& _enum) override;
void endVisit(EnumDefinition& _enum) override;
bool visit(EnumValue& _value) override;
bool visit(FunctionDefinition& _function) override;
void endVisit(FunctionDefinition& _function) override;
bool visit(ModifierDefinition& _modifier) override;

35
libsolidity/Parser.cpp

@ -119,6 +119,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
ASTPointer<ASTString> name = expectIdentifierToken();
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
vector<ASTPointer<StructDefinition>> structs;
vector<ASTPointer<EnumDefinition>> enums;
vector<ASTPointer<VariableDeclaration>> stateVariables;
vector<ASTPointer<FunctionDefinition>> functions;
vector<ASTPointer<ModifierDefinition>> modifiers;
@ -140,6 +141,8 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
functions.push_back(parseFunctionDefinition(name.get()));
else if (currentToken == Token::Struct)
structs.push_back(parseStructDefinition());
else if (currentToken == Token::Enum)
enums.push_back(parseEnumDefinition());
else if (currentToken == Token::Identifier || currentToken == Token::Mapping ||
Token::isElementaryTypeName(currentToken))
{
@ -157,7 +160,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
}
nodeFactory.markEndPosition();
expectToken(Token::RBrace);
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs,
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, enums,
stateVariables, functions, modifiers, events);
}
@ -263,6 +266,36 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
return nodeFactory.createNode<StructDefinition>(name, members);
}
ASTPointer<EnumValue> Parser::parseEnumValue()
{
ASTNodeFactory nodeFactory(*this);
nodeFactory.markEndPosition();
return nodeFactory.createNode<EnumValue>(expectIdentifierToken());
}
ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
{
ASTNodeFactory nodeFactory(*this);
expectToken(Token::Enum);
ASTPointer<ASTString> name = expectIdentifierToken();
vector<ASTPointer<EnumValue>> members;
expectToken(Token::LBrace);
while (m_scanner->getCurrentToken() != Token::RBrace)
{
members.push_back(parseEnumValue());
if (m_scanner->getCurrentToken() == Token::RBrace)
break;
expectToken(Token::Comma);
if (m_scanner->getCurrentToken() != Token::Identifier)
BOOST_THROW_EXCEPTION(createParserError("Expected Identifier after ','"));
}
nodeFactory.markEndPosition();
expectToken(Token::RBrace);
return nodeFactory.createNode<EnumDefinition>(name, members);
}
ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options)
{
ASTNodeFactory nodeFactory(*this);

2
libsolidity/Parser.h

@ -61,6 +61,8 @@ private:
Declaration::Visibility parseVisibilitySpecifier(Token::Value _token);
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
ASTPointer<StructDefinition> parseStructDefinition();
ASTPointer<EnumDefinition> parseEnumDefinition();
ASTPointer<EnumValue> parseEnumValue();
ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
ASTPointer<ModifierDefinition> parseModifierDefinition();
ASTPointer<EventDefinition> parseEventDefinition();

80
libsolidity/Token.h

@ -67,31 +67,31 @@ namespace solidity
#define IGNORE_TOKEN(name, string, precedence)
#define TOKEN_LIST(T, K) \
/* End of source indicator. */ \
T(EOS, "EOS", 0) \
#define TOKEN_LIST(T, K) \
/* End of source indicator. */ \
T(EOS, "EOS", 0) \
\
/* Punctuators (ECMA-262, section 7.7, page 15). */ \
T(LParen, "(", 0) \
T(RParen, ")", 0) \
T(LBrack, "[", 0) \
T(RBrack, "]", 0) \
T(LBrace, "{", 0) \
T(RBrace, "}", 0) \
T(Colon, ":", 0) \
T(Semicolon, ";", 0) \
T(Period, ".", 0) \
T(Conditional, "?", 3) \
T(Arrow, "=>", 0) \
\
/* Punctuators (ECMA-262, section 7.7, page 15). */ \
T(LParen, "(", 0) \
T(RParen, ")", 0) \
T(LBrack, "[", 0) \
T(RBrack, "]", 0) \
T(LBrace, "{", 0) \
T(RBrace, "}", 0) \
T(Colon, ":", 0) \
T(Semicolon, ";", 0) \
T(Period, ".", 0) \
T(Conditional, "?", 3) \
T(Arrow, "=>", 0) \
\
/* Assignment operators. */ \
/* IsAssignmentOp() relies on this block of enum values being */ \
/* contiguous and sorted in the same order!*/ \
T(Assign, "=", 2) \
/* Assignment operators. */ \
/* IsAssignmentOp() relies on this block of enum values being */ \
/* contiguous and sorted in the same order!*/ \
T(Assign, "=", 2) \
/* The following have to be in exactly the same order as the simple binary operators*/ \
T(AssignBitOr, "|=", 2) \
T(AssignBitXor, "^=", 2) \
T(AssignBitAnd, "&=", 2) \
T(AssignBitOr, "|=", 2) \
T(AssignBitXor, "^=", 2) \
T(AssignBitAnd, "&=", 2) \
T(AssignShl, "<<=", 2) \
T(AssignSar, ">>=", 2) \
T(AssignShr, ">>>=", 2) \
@ -107,9 +107,9 @@ namespace solidity
T(Comma, ",", 1) \
T(Or, "||", 4) \
T(And, "&&", 5) \
T(BitOr, "|", 8) \
T(BitXor, "^", 9) \
T(BitAnd, "&", 10) \
T(BitOr, "|", 8) \
T(BitXor, "^", 9) \
T(BitAnd, "&", 10) \
T(SHL, "<<", 11) \
T(SAR, ">>", 11) \
T(SHR, ">>>", 11) \
@ -123,19 +123,19 @@ namespace solidity
/* Compare operators sorted by precedence. */ \
/* IsCompareOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(Equal, "==", 6) \
T(NotEqual, "!=", 6) \
T(LessThan, "<", 7) \
T(GreaterThan, ">", 7) \
T(LessThanOrEqual, "<=", 7) \
T(GreaterThanOrEqual, ">=", 7) \
T(Equal, "==", 6) \
T(NotEqual, "!=", 6) \
T(LessThan, "<", 7) \
T(GreaterThan, ">", 7) \
T(LessThanOrEqual, "<=", 7) \
T(GreaterThanOrEqual, ">=", 7) \
K(In, "in", 7) \
\
/* Unary operators. */ \
/* IsUnaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(Not, "!", 0) \
T(BitNot, "~", 0) \
T(BitNot, "~", 0) \
T(Inc, "++", 0) \
T(Dec, "--", 0) \
K(Delete, "delete", 0) \
@ -168,7 +168,7 @@ namespace solidity
K(Switch, "switch", 0) \
K(Var, "var", 0) \
K(While, "while", 0) \
\
K(Enum, "enum", 0) \
\
/* Ether subdenominations */ \
K(SubWei, "wei", 0) \
@ -316,15 +316,15 @@ namespace solidity
K(Text, "text", 0) \
K(Real, "real", 0) \
K(UReal, "ureal", 0) \
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
\
/* Literals */ \
K(NullLiteral, "null", 0) \
K(TrueLiteral, "true", 0) \
K(FalseLiteral, "false", 0) \
K(NullLiteral, "null", 0) \
K(TrueLiteral, "true", 0) \
K(FalseLiteral, "false", 0) \
T(Number, NULL, 0) \
T(StringLiteral, NULL, 0) \
T(CommentLiteral, NULL, 0) \
T(StringLiteral, NULL, 0) \
T(CommentLiteral, NULL, 0) \
\
/* Identifiers (not keywords or future reserved words). */ \
T(Identifier, NULL, 0) \

48
libsolidity/Types.cpp

@ -74,6 +74,8 @@ TypePointer Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName)
Declaration const* declaration = _typeName.getReferencedDeclaration();
if (StructDefinition const* structDef = dynamic_cast<StructDefinition const*>(declaration))
return make_shared<StructType>(*structDef);
else if (EnumDefinition const* enumDef = dynamic_cast<EnumDefinition const*>(declaration))
return make_shared<EnumType>(*enumDef);
else if (FunctionDefinition const* function = dynamic_cast<FunctionDefinition const*>(declaration))
return make_shared<FunctionType>(*function);
else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration))
@ -154,7 +156,9 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
StaticStringType const& convertTo = dynamic_cast<StaticStringType const&>(_convertTo);
return isHash() && (m_bits == convertTo.getNumBytes() * 8);
}
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::Contract;
return _convertTo.getCategory() == getCategory() ||
_convertTo.getCategory() == Category::Contract ||
_convertTo.getCategory() == Category::Enum;
}
TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const
@ -662,6 +666,41 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
}
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared<VoidType>() : TypePointer();
}
bool EnumType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())
return false;
EnumType const& other = dynamic_cast<EnumType const&>(_other);
return other.m_enum == m_enum;
}
string EnumType::toString() const
{
return string("enum ") + m_enum.getName();
}
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::Integer;
}
unsigned int EnumType::getMemberValue(ASTString const& _member) const
{
unsigned int index = 0;
for (ASTPointer<EnumValue> const& decl: m_enum.getMembers())
{
if (decl->getName() == _member)
return index;
++index;
}
BOOST_THROW_EXCEPTION(m_enum.createTypeError("Requested unknown enum value ." + _member));
}
FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal):
m_location(_isInternal ? Location::Internal : Location::External),
m_isConstant(_function.isDeclaredConst()),
@ -924,6 +963,13 @@ MemberList const& TypeType::getMembers() const
if (!f->isConstructor() && !f->getName().empty())
members[f->getName()] = make_shared<FunctionType>(*f);
}
else if (m_actualType->getCategory() == Category::Enum)
{
EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).getEnumDefinition();
auto enumType = make_shared<EnumType>(enumDef);
for (ASTPointer<EnumValue> const& enumValue: enumDef.getMembers())
members.insert(make_pair(enumValue->getName(), enumType));
}
m_members.reset(new MemberList(members));
}
return *m_members;

33
libsolidity/Types.h

@ -76,10 +76,9 @@ class Type: private boost::noncopyable, public std::enable_shared_from_this<Type
public:
enum class Category
{
Integer, IntegerConstant, Bool, Real, String,
ByteArray, Mapping,
Contract, Struct, Function,
Void, TypeType, Modifier, Magic
Integer, IntegerConstant, Bool, Real, ByteArray,
String, Contract, Struct, Function, Enum,
Mapping, Void, TypeType, Modifier, Magic
};
///@{
@ -368,6 +367,32 @@ private:
mutable std::unique_ptr<MemberList> m_members;
};
/**
* The type of an enum instance, there is one distinct type per enum definition.
*/
class EnumType: public Type
{
public:
virtual Category getCategory() const override { return Category::Enum; }
explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {}
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual bool operator==(Type const& _other) const override;
virtual unsigned getSizeOnStack() const override { return 1; }
virtual std::string toString() const override;
virtual bool isValueType() const override { return true; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
EnumDefinition const& getEnumDefinition() const { return m_enum; }
/// @returns the value that the string has in the Enum
unsigned int getMemberValue(ASTString const& _member) const;
private:
EnumDefinition const& m_enum;
/// List of member types, will be lazy-initialized because of recursive references.
mutable std::unique_ptr<MemberList> m_members;
};
/**
* The type of a function, identified by its (return) parameter types.
* @todo the return parameters should also have names, i.e. return parameters should be a struct

5
libsolidity/grammar.txt

@ -1,7 +1,7 @@
ContractDefinition = 'contract' Identifier
( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )?
'{' ContractPart* '}'
ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition
ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition | EnumDefinition
InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )?
StructDefinition = 'struct' Identifier '{'
@ -11,6 +11,9 @@ ModifierDefinition = 'modifier' Identifier ParameterList? Block
FunctionDefinition = 'function' Identifier ParameterList
( Identifier | 'constant' | 'public' | 'protected' | 'private' )*
( 'returns' ParameterList )? Block
EnumValue = Identifier
EnumDefinition = 'enum' '{' EnumValue (',' EnumValue)* '}'
ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists

5
libweb3jsonrpc/CMakeLists.txt

@ -9,9 +9,11 @@ set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(..)
include_directories(${JSONCPP_INCLUDE_DIRS})
include_directories(${MHD_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(..)
set(EXECUTABLE web3jsonrpc)
@ -26,6 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${MHD_LIBRARIES})
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} secp256k1)

28
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -264,7 +264,7 @@ Json::Value WebThreeStubServerBase::eth_blockByHash(std::string const& _hash)
return toJson(client()->blockInfo(jsToFixed<32>(_hash)));
}
Json::Value WebThreeStubServerBase::eth_blockByNumber(int const& _number)
Json::Value WebThreeStubServerBase::eth_blockByNumber(int _number)
{
return toJson(client()->blockInfo(client()->hashFromNumber(_number)));
}
@ -279,6 +279,8 @@ static TransactionSkeleton toTransaction(Json::Value const& _json)
ret.from = jsToAddress(_json["from"].asString());
if (_json["to"].isString())
ret.to = jsToAddress(_json["to"].asString());
else
ret.creation = true;
if (!_json["value"].empty())
{
if (_json["value"].isString())
@ -342,7 +344,7 @@ std::string WebThreeStubServerBase::eth_call(Json::Value const& _json)
return ret;
}
Json::Value WebThreeStubServerBase::eth_changed(int const& _id)
Json::Value WebThreeStubServerBase::eth_changed(int _id)
{
auto entries = client()->checkWatch(_id);
if (entries.size())
@ -381,7 +383,7 @@ std::string WebThreeStubServerBase::db_get(std::string const& _name, std::string
return toJS(dev::asBytes(ret));
}
Json::Value WebThreeStubServerBase::eth_filterLogs(int const& _id)
Json::Value WebThreeStubServerBase::eth_filterLogs(int _id)
{
return toJson(client()->logs(_id));
}
@ -563,13 +565,13 @@ bool WebThreeStubServerBase::eth_setCoinbase(std::string const& _address)
return true;
}
bool WebThreeStubServerBase::eth_setDefaultBlock(int const& _block)
bool WebThreeStubServerBase::eth_setDefaultBlock(int _block)
{
client()->setDefault(_block);
return true;
}
bool WebThreeStubServerBase::eth_setListening(bool const& _listening)
bool WebThreeStubServerBase::eth_setListening(bool _listening)
{
if (_listening)
network()->startNetwork();
@ -578,7 +580,7 @@ bool WebThreeStubServerBase::eth_setListening(bool const& _listening)
return true;
}
bool WebThreeStubServerBase::eth_setMining(bool const& _mining)
bool WebThreeStubServerBase::eth_setMining(bool _mining)
{
if (_mining)
client()->startMining();
@ -587,7 +589,7 @@ bool WebThreeStubServerBase::eth_setMining(bool const& _mining)
return true;
}
Json::Value WebThreeStubServerBase::shh_changed(int const& _id)
Json::Value WebThreeStubServerBase::shh_changed(int _id)
{
Json::Value ret(Json::arrayValue);
auto pub = m_shhWatches[_id];
@ -619,7 +621,7 @@ int WebThreeStubServerBase::shh_newFilter(Json::Value const& _json)
return ret;
}
bool WebThreeStubServerBase::shh_uninstallFilter(int const& _id)
bool WebThreeStubServerBase::shh_uninstallFilter(int _id)
{
face()->uninstallWatch(_id);
return true;
@ -671,27 +673,27 @@ bool WebThreeStubServerBase::authenticate(TransactionSkeleton const& _t)
return true;
}
Json::Value WebThreeStubServerBase::eth_transactionByHash(std::string const& _hash, int const& _i)
Json::Value WebThreeStubServerBase::eth_transactionByHash(std::string const& _hash, int _i)
{
return toJson(client()->transaction(jsToFixed<32>(_hash), _i));
}
Json::Value WebThreeStubServerBase::eth_transactionByNumber(int const& _number, int const& _i)
Json::Value WebThreeStubServerBase::eth_transactionByNumber(int _number, int _i)
{
return toJson(client()->transaction(client()->hashFromNumber(_number), _i));
}
Json::Value WebThreeStubServerBase::eth_uncleByHash(std::string const& _hash, int const& _i)
Json::Value WebThreeStubServerBase::eth_uncleByHash(std::string const& _hash, int _i)
{
return toJson(client()->uncle(jsToFixed<32>(_hash), _i));
}
Json::Value WebThreeStubServerBase::eth_uncleByNumber(int const& _number, int const& _i)
Json::Value WebThreeStubServerBase::eth_uncleByNumber(int _number, int _i)
{
return toJson(client()->uncle(client()->hashFromNumber(_number), _i));
}
bool WebThreeStubServerBase::eth_uninstallFilter(int const& _id)
bool WebThreeStubServerBase::eth_uninstallFilter(int _id)
{
client()->uninstallWatch(_id);
return true;

26
libweb3jsonrpc/WebThreeStubServerBase.h

@ -69,16 +69,16 @@ public:
virtual Json::Value eth_accounts();
virtual std::string eth_balanceAt(std::string const& _address);
virtual Json::Value eth_blockByHash(std::string const& _hash);
virtual Json::Value eth_blockByNumber(int const& _number);
virtual Json::Value eth_blockByNumber(int _number);
virtual std::string eth_call(Json::Value const& _json);
virtual Json::Value eth_changed(int const& _id);
virtual Json::Value eth_changed(int _id);
virtual std::string eth_codeAt(std::string const& _address);
virtual std::string eth_coinbase();
virtual Json::Value eth_compilers();
virtual double eth_countAt(std::string const& _address);
virtual int eth_defaultBlock();
virtual std::string eth_gasPrice();
virtual Json::Value eth_filterLogs(int const& _id);
virtual Json::Value eth_filterLogs(int _id);
virtual bool eth_flush();
virtual Json::Value eth_logs(Json::Value const& _json);
virtual bool eth_listening();
@ -88,20 +88,20 @@ public:
virtual int eth_number();
virtual int eth_peerCount();
virtual bool eth_setCoinbase(std::string const& _address);
virtual bool eth_setDefaultBlock(int const& _block);
virtual bool eth_setListening(bool const& _listening);
virtual bool eth_setDefaultBlock(int _block);
virtual bool eth_setListening(bool _listening);
virtual std::string eth_lll(std::string const& _s);
virtual std::string eth_serpent(std::string const& _s);
virtual bool eth_setMining(bool const& _mining);
virtual bool eth_setMining(bool _mining);
virtual std::string eth_solidity(std::string const& _code);
virtual std::string eth_stateAt(std::string const& _address, std::string const& _storage);
virtual Json::Value eth_storageAt(std::string const& _address);
virtual std::string eth_transact(Json::Value const& _json);
virtual Json::Value eth_transactionByHash(std::string const& _hash, int const& _i);
virtual Json::Value eth_transactionByNumber(int const& _number, int const& _i);
virtual Json::Value eth_uncleByHash(std::string const& _hash, int const& _i);
virtual Json::Value eth_uncleByNumber(int const& _number, int const& _i);
virtual bool eth_uninstallFilter(int const& _id);
virtual Json::Value eth_transactionByHash(std::string const& _hash, int _i);
virtual Json::Value eth_transactionByNumber(int _number, int _i);
virtual Json::Value eth_uncleByHash(std::string const& _hash, int _i);
virtual Json::Value eth_uncleByNumber(int _number, int _i);
virtual bool eth_uninstallFilter(int _id);
virtual Json::Value eth_getWork();
virtual bool eth_submitWork(std::string const& _nonce);
@ -112,13 +112,13 @@ public:
virtual bool db_putString(std::string const& _name, std::string const& _key, std::string const& _value);
virtual std::string shh_addToGroup(std::string const& _group, std::string const& _who);
virtual Json::Value shh_changed(int const& _id);
virtual Json::Value shh_changed(int _id);
virtual bool shh_haveIdentity(std::string const& _id);
virtual int shh_newFilter(Json::Value const& _json);
virtual std::string shh_newGroup(std::string const& _id, std::string const& _who);
virtual std::string shh_newIdentity();
virtual bool shh_post(Json::Value const& _json);
virtual bool shh_uninstallFilter(int const& _id);
virtual bool shh_uninstallFilter(int _id);
void setAccounts(std::vector<dev::KeyPair> const& _accounts);
void setIdentities(std::vector<dev::KeyPair> const& _ids);

146
libweb3jsonrpc/abstractwebthreestubserver.h

@ -10,59 +10,59 @@
class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThreeStubServer>
{
public:
AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector &conn) : jsonrpc::AbstractServer<AbstractWebThreeStubServer>(conn)
{
this->bindAndAddMethod(new jsonrpc::Procedure("web3_sha3", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::web3_sha3I);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_setCoinbaseI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setListeningI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setMiningI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_accountsI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_peerCountI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_setDefaultBlockI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_numberI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_balanceAtI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_stateAtI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_storageAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_storageAtI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_transactI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_callI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_flush", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_flushI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_blockByHashI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_blockByNumberI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByHashI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByNumberI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_uncleByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByHashI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_uncleByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByNumberI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_solidityI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_serpent", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_serpentI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uninstallFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_getWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_getWorkI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_submitWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_submitWorkI);
this->bindAndAddMethod(new jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI);
this->bindAndAddMethod(new jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI);
this->bindAndAddMethod(new jsonrpc::Procedure("db_putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putStringI);
this->bindAndAddMethod(new jsonrpc::Procedure("db_getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getStringI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_postI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newIdentityI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_haveIdentityI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newGroupI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_addToGroupI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_newFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_uninstallFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("shh_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_changedI);
AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector &conn, jsonrpc::serverVersion_t type = jsonrpc::JSONRPC_SERVER_V2) : jsonrpc::AbstractServer<AbstractWebThreeStubServer>(conn, type)
{
this->bindAndAddMethod(jsonrpc::Procedure("web3_sha3", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::web3_sha3I);
this->bindAndAddMethod(jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_setCoinbaseI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setListeningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setMiningI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_accountsI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_peerCountI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_setDefaultBlockI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_numberI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_balanceAtI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_stateAtI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_storageAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_storageAtI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_transactI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_callI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_flush", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_flushI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_blockByHashI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_blockByNumberI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByHashI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByNumberI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_uncleByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByHashI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_uncleByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByNumberI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_solidityI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_serpent", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_serpentI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uninstallFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_getWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_getWorkI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_submitWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_submitWorkI);
this->bindAndAddMethod(jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI);
this->bindAndAddMethod(jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI);
this->bindAndAddMethod(jsonrpc::Procedure("db_putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putStringI);
this->bindAndAddMethod(jsonrpc::Procedure("db_getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getStringI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_postI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newIdentityI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_haveIdentityI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newGroupI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_addToGroupI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_newFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_uninstallFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_changedI);
}
inline virtual void web3_sha3I(const Json::Value &request, Json::Value &response)
@ -71,6 +71,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_coinbaseI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_coinbase();
}
inline virtual void eth_setCoinbaseI(const Json::Value &request, Json::Value &response)
@ -79,6 +80,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_listeningI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_listening();
}
inline virtual void eth_setListeningI(const Json::Value &request, Json::Value &response)
@ -87,6 +89,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_miningI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_mining();
}
inline virtual void eth_setMiningI(const Json::Value &request, Json::Value &response)
@ -95,18 +98,22 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_gasPriceI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_gasPrice();
}
inline virtual void eth_accountsI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_accounts();
}
inline virtual void eth_peerCountI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_peerCount();
}
inline virtual void eth_defaultBlockI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_defaultBlock();
}
inline virtual void eth_setDefaultBlockI(const Json::Value &request, Json::Value &response)
@ -115,6 +122,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_numberI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_number();
}
inline virtual void eth_balanceAtI(const Json::Value &request, Json::Value &response)
@ -147,6 +155,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_flushI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_flush();
}
inline virtual void eth_blockByHashI(const Json::Value &request, Json::Value &response)
@ -175,6 +184,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_compilersI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_compilers();
}
inline virtual void eth_lllI(const Json::Value &request, Json::Value &response)
@ -215,6 +225,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_getWorkI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_getWork();
}
inline virtual void eth_submitWorkI(const Json::Value &request, Json::Value &response)
@ -243,6 +254,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void shh_newIdentityI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->shh_newIdentity();
}
inline virtual void shh_haveIdentityI(const Json::Value &request, Json::Value &response)
@ -273,14 +285,14 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string eth_coinbase() = 0;
virtual bool eth_setCoinbase(const std::string& param1) = 0;
virtual bool eth_listening() = 0;
virtual bool eth_setListening(const bool& param1) = 0;
virtual bool eth_setListening(bool param1) = 0;
virtual bool eth_mining() = 0;
virtual bool eth_setMining(const bool& param1) = 0;
virtual bool eth_setMining(bool param1) = 0;
virtual std::string eth_gasPrice() = 0;
virtual Json::Value eth_accounts() = 0;
virtual int eth_peerCount() = 0;
virtual int eth_defaultBlock() = 0;
virtual bool eth_setDefaultBlock(const int& param1) = 0;
virtual bool eth_setDefaultBlock(int param1) = 0;
virtual int eth_number() = 0;
virtual std::string eth_balanceAt(const std::string& param1) = 0;
virtual std::string eth_stateAt(const std::string& param1, const std::string& param2) = 0;
@ -291,20 +303,20 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string eth_call(const Json::Value& param1) = 0;
virtual bool eth_flush() = 0;
virtual Json::Value eth_blockByHash(const std::string& param1) = 0;
virtual Json::Value eth_blockByNumber(const int& param1) = 0;
virtual Json::Value eth_transactionByHash(const std::string& param1, const int& param2) = 0;
virtual Json::Value eth_transactionByNumber(const int& param1, const int& param2) = 0;
virtual Json::Value eth_uncleByHash(const std::string& param1, const int& param2) = 0;
virtual Json::Value eth_uncleByNumber(const int& param1, const int& param2) = 0;
virtual Json::Value eth_blockByNumber(int param1) = 0;
virtual Json::Value eth_transactionByHash(const std::string& param1, int param2) = 0;
virtual Json::Value eth_transactionByNumber(int param1, int param2) = 0;
virtual Json::Value eth_uncleByHash(const std::string& param1, int param2) = 0;
virtual Json::Value eth_uncleByNumber(int param1, int param2) = 0;
virtual Json::Value eth_compilers() = 0;
virtual std::string eth_lll(const std::string& param1) = 0;
virtual std::string eth_solidity(const std::string& param1) = 0;
virtual std::string eth_serpent(const std::string& param1) = 0;
virtual int eth_newFilter(const Json::Value& param1) = 0;
virtual int eth_newFilterString(const std::string& param1) = 0;
virtual bool eth_uninstallFilter(const int& param1) = 0;
virtual Json::Value eth_changed(const int& param1) = 0;
virtual Json::Value eth_filterLogs(const int& param1) = 0;
virtual bool eth_uninstallFilter(int param1) = 0;
virtual Json::Value eth_changed(int param1) = 0;
virtual Json::Value eth_filterLogs(int param1) = 0;
virtual Json::Value eth_logs(const Json::Value& param1) = 0;
virtual Json::Value eth_getWork() = 0;
virtual bool eth_submitWork(const std::string& param1) = 0;
@ -318,8 +330,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string shh_newGroup(const std::string& param1, const std::string& param2) = 0;
virtual std::string shh_addToGroup(const std::string& param1, const std::string& param2) = 0;
virtual int shh_newFilter(const Json::Value& param1) = 0;
virtual bool shh_uninstallFilter(const int& param1) = 0;
virtual Json::Value shh_changed(const int& param1) = 0;
virtual bool shh_uninstallFilter(int param1) = 0;
virtual Json::Value shh_changed(int param1) = 0;
};
#endif //JSONRPC_CPP_ABSTRACTWEBTHREESTUBSERVER_H_
#endif //JSONRPC_CPP_STUB_ABSTRACTWEBTHREESTUBSERVER_H_

2
mix/Web3Server.cpp

@ -55,7 +55,7 @@ void Web3Server::put(std::string const& _name, std::string const& _key, std::str
m_db[k] = _value;
}
Json::Value Web3Server::eth_changed(int const& _id)
Json::Value Web3Server::eth_changed(int _id)
{
return WebThreeStubServerBase::eth_changed(_id);
}

2
mix/Web3Server.h

@ -44,7 +44,7 @@ signals:
void newTransaction();
protected:
virtual Json::Value eth_changed(int const& _id) override;
virtual Json::Value eth_changed(int _id) override;
virtual std::string eth_transact(Json::Value const& _json) override;
virtual std::string eth_call(Json::Value const& _json) override;

2
mix/qml/BasicMessage.qml

@ -1,6 +1,6 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1

3
mix/qml/CodeEditorView.qml

@ -19,7 +19,8 @@ Item {
function isDocumentOpen(documentId) {
for (var i = 0; i < editorListModel.count; i++)
if (editorListModel.get(i).documentId === documentId)
if (editorListModel.get(i).documentId === documentId &&
editors.itemAt(i).item)
return true;
return false;
}

6
mix/qml/Debugger.qml

@ -1,6 +1,6 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import Qt.labs.settings 1.0
@ -598,9 +598,11 @@ Rectangle {
Layout.minimumWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Text {
maximumLineCount: 1
clip: true
anchors.leftMargin: 5
width: parent.width - 5
wrapMode: Text.NoWrap
wrapMode: Text.WrapAnywhere
anchors.left: parent.left
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter

2
mix/qml/StateList.qml

@ -1,6 +1,6 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0

2
mix/qml/StateListModel.qml

@ -1,6 +1,6 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1

2
mix/qml/TransactionLog.qml

@ -1,6 +1,6 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1

124
mix/qml/WebPreview.qml

@ -6,6 +6,7 @@ import QtQuick.Controls.Styles 1.1
import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
import HttpServer 1.0
import "."
Item {
id: webPreview
@ -38,7 +39,7 @@ Item {
function updateDocument(documentId, action) {
for (var i = 0; i < pageListModel.count; i++)
if (pageListModel.get(i).documentId === i)
if (pageListModel.get(i).documentId === documentId)
action(i);
}
@ -82,10 +83,22 @@ Item {
onDocumentRemoved: {
updateDocument(documentId, function(i) { pageListModel.remove(i) } )
}
onDocumentUpdated: {
updateDocument(documentId, function(i) { pageListModel.set(i, projectModel.getDocument(documentId)) } )
}
onDocumentOpened: {
if (!document.isHtml)
return;
for (var i = 0; i < pageListModel.count; i++) {
var doc = pageListModel.get(i);
if (doc.documentId === document.documentId) {
pageCombo.currentIndex = i;
}
}
}
onProjectLoading: {
for (var i = 0; i < target.listModel.count; i++) {
var document = target.listModel.get(i);
@ -146,45 +159,86 @@ Item {
ColumnLayout {
anchors.fill: parent
RowLayout {
anchors.top: parent.top
Layout.fillWidth: true;
Text {
text: qsTr("Page")
}
ComboBox {
id: pageCombo
model: pageListModel
textRole: "name"
currentIndex: -1
onCurrentIndexChanged: changePage()
}
Button {
text: qsTr("Reload")
onClicked: reload()
spacing: 0
Rectangle
{
SourceSansProLight
{
id: regularFont
}
CheckBox {
id: autoReloadOnSave
checked: true
text: qsTr("Auto reload on save")
anchors.leftMargin: 4
color: WebPreviewStyle.general.headerBackgroundColor
Layout.preferredWidth: parent.width
Layout.preferredHeight: 32
Row {
anchors.top: parent.top
anchors.fill: parent
anchors.leftMargin: 3
spacing: 3
DefaultLabel {
text: qsTr("Preview of")
anchors.verticalCenter: parent.verticalCenter
}
ComboBox {
id: pageCombo
model: pageListModel
textRole: "name"
currentIndex: -1
onCurrentIndexChanged: changePage()
anchors.verticalCenter: parent.verticalCenter
style: ComboBoxStyle {
font: regularFont.name
}
}
Action {
tooltip: qsTr("Reload")
id: buttonReloadAction
onTriggered: {
reload();
}
}
Button {
iconSource: "qrc:/qml/img/available_updates.png"
action: buttonReloadAction
anchors.verticalCenter: parent.verticalCenter
width: 26
height: 26
}
CheckBox {
id: autoReloadOnSave
checked: true
anchors.verticalCenter: parent.verticalCenter
style: CheckBoxStyle {
label: DefaultLabel {
text: qsTr("Auto reload on save")
}
}
}
}
}
WebEngineView {
Layout.fillWidth: true
Rectangle
{
Layout.preferredWidth: parent.width
Layout.fillHeight: true
id: webView
experimental.settings.localContentCanAccessRemoteUrls: true
onJavaScriptConsoleMessage: {
console.log(sourceID + ":" + lineNumber + ":" + message);
}
onLoadingChanged: {
if (!loading) {
initialized = true;
webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")");
if (pendingPageUrl)
setPreviewUrl(pendingPageUrl);
WebEngineView {
anchors.fill: parent
id: webView
experimental.settings.localContentCanAccessRemoteUrls: true
onJavaScriptConsoleMessage: {
console.log(sourceID + ":" + lineNumber + ":" + message);
}
onLoadingChanged: {
if (!loading) {
initialized = true;
webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")");
if (pendingPageUrl)
setPreviewUrl(pendingPageUrl);
}
}
}
}

14
mix/qml/WebPreviewStyle.qml

@ -0,0 +1,14 @@
pragma Singleton
import QtQuick 2.0
QtObject {
function absoluteSize(rel)
{
return systemPointSize + rel;
}
property QtObject general: QtObject {
property string headerBackgroundColor: "#f0f0f0"
}
}

BIN
mix/qml/img/available_updates.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

1
mix/qml/qmldir

@ -4,3 +4,4 @@ singleton ProjectFilesStyle 1.0 ProjectFilesStyle.qml
singleton DebuggerPaneStyle 1.0 DebuggerPaneStyle.qml
singleton StateStyle 1.0 StateStyle.qml
singleton StatusPaneStyle 1.0 StatusPaneStyle.qml
singleton WebPreviewStyle 1.0 WebPreviewStyle.qml

2
mix/res.qrc

@ -97,5 +97,7 @@
<file>qml/DefaultTextField.qml</file>
<file>qml/CommonSeparator.qml</file>
<file>qml/Style.qml</file>
<file>qml/WebPreviewStyle.qml</file>
<file>qml/img/available_updates.png</file>
</qresource>
</RCC>

17
test/PerformaceTester.sol

@ -0,0 +1,17 @@
contract PerformanceTester {
function ackermann(uint m, uint n) returns (uint) {
if (m == 0)
return n + 1;
if (n == 0)
return ackermann(m - 1, 1);
return ackermann(m - 1, ackermann(m, n - 1));
}
function fibonacci(uint n) returns (uint) {
if (n == 0 || n == 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
}

35
test/SolidityEndToEndTest.cpp

@ -2499,6 +2499,41 @@ BOOST_AUTO_TEST_CASE(struct_copy_via_local)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
}
BOOST_AUTO_TEST_CASE(using_enums)
{
char const* sourceCode = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
choices = ActionChoices.GoStraight;
}
function getChoice() returns (uint d)
{
d = uint256(choices);
}
ActionChoices choices;
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(constructing_enums_from_ints)
{
char const* sourceCode = R"(
contract c {
enum Truth { False, True }
function test() returns (uint)
{
return uint(Truth(uint8(0x701)));
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(1));
}
BOOST_AUTO_TEST_SUITE_END()
}

91
test/SolidityNameAndTypeResolution.cpp

@ -992,6 +992,97 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(enum_member_access)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
choices = ActionChoices.GoStraight;
}
ActionChoices choices;
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(text));
}
BOOST_AUTO_TEST_CASE(enum_invalid_member_access)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
choices = ActionChoices.RunAroundWavingYourHands;
}
ActionChoices choices;
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
a = uint256(ActionChoices.GoStraight);
b = uint64(ActionChoices.Sit);
}
uint256 a;
uint64 b;
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(text));
}
BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
a = 2;
b = ActionChoices(a);
}
uint256 a;
ActionChoices b;
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(text));
}
BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test()
{
a = ActionChoices.GoStraight;
b = ActionChoices.Sit;
}
uint256 a;
uint64 b;
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(enum_duplicate_values)
{
char const* text = R"(
contract test {
enum ActionChoices { GoLeft, GoRight, GoLeft, Sit }
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
}
BOOST_AUTO_TEST_SUITE_END()
}

32
test/SolidityParser.cpp

@ -703,6 +703,38 @@ BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations_in_expression
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_CASE(enum_valid_declaration)
{
char const* text = R"(
contract c {
enum validEnum { Value1, Value2, Value3, Value4 }
function c ()
{
a = foo.Value3;
}
uint256 a;
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_CASE(empty_enum_declaration)
{
char const* text = R"(
contract c {
enum foo { }
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_CASE(malformed_enum_declaration)
{
char const* text = R"(
contract c {
enum foo { WARNING,}
})";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_SUITE_END()
}

4
test/vm.cpp

@ -525,7 +525,7 @@ BOOST_AUTO_TEST_CASE(vmPerformanceTest)
dev::test::executeTests("vmPerformanceTest", "/VMTests", dev::test::doVMTests);
auto end = chrono::steady_clock::now();
chrono::milliseconds duration(chrono::duration_cast<chrono::milliseconds>(end - start));
auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
cnote << "test duration: " << duration.count() << " milliseconds.\n";
}
}
@ -543,7 +543,7 @@ BOOST_AUTO_TEST_CASE(vmInputLimitsTest1)
dev::test::executeTests("vmInputLimitsTest1", "/VMTests", dev::test::doVMTests);
auto end = chrono::steady_clock::now();
chrono::milliseconds duration(chrono::duration_cast<chrono::milliseconds>(end - start));
auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
cnote << "test duration: " << duration.count() << " milliseconds.\n";
}
}

131
test/vmPerformanceTestFiller.json

@ -1,4 +1,62 @@
{
"ackermann31": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "100000000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"//" : "PerformanceTester.sol",
"code" : "0x60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"//" : "ackermann(3, 1)",
"data" : "0x2839e92800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"ackermann32": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "100000000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"//" : "PerformanceTester.sol",
"code" : "0x60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"//" : "ackermann(3, 2)",
"data" : "0x2839e92800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"ackermann33": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
@ -12,16 +70,8 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"//" : "contract PerformanceTester {",
"//" : " function ackermann(uint m, uint n) returns (uint) {",
"//" : " if (m == 0)",
"//" : " return n + 1;",
"//" : " if (n == 0)",
"//" : " return ackermann(m - 1, 1);",
"//" : " return ackermann(m - 1, ackermann(m, n - 1));",
"//" : " }",
"//" : "}",
"code" : "0x60e060020a6000350480632839e92814601457005b6020600435602435602a565b8060005260206000f35b6000826000146037576041565b8160010190506076565b81600014604c57605e565b6058600184036001602a565b90506076565b607360018403606f8560018603602a565b602a565b90505b9291505056",
"//" : "PerformanceTester.sol",
"code" : "0x60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056",
"storage": {}
}
},
@ -30,9 +80,68 @@
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"//" : "ackermann(3, 3)",
"data" : "0x2839e92800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003",
"gasPrice" : "100000000000000",
"gas" : "100000000000"
"gas" : "100000"
}
},
"fibonacci10": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "100000000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"//" : "PerformanceTester.sol",
"code" : "0x60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"//" : "fibonacci(10)",
"data" : "0x61047ff4000000000000000000000000000000000000000000000000000000000000000a",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"fibonacci16": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "100000000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"//" : "PerformanceTester.sol",
"code" : "0x60e060020a6000350480632839e92814601e57806361047ff414603457005b602a6004356024356047565b8060005260206000f35b603d6004356099565b8060005260206000f35b600082600014605457605e565b8160010190506093565b81600014606957607b565b60756001840360016047565b90506093565b609060018403608c85600186036047565b6047565b90505b92915050565b6000816000148060a95750816001145b60b05760b7565b81905060cf565b60c1600283036099565b60cb600184036099565b0190505b91905056",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"//" : "fibonacci(16)",
"data" : "0x61047ff40000000000000000000000000000000000000000000000000000000000000010",
"gasPrice" : "100000000000000",
"gas" : "100000000"
}
}
}

30
test/webthreestubclient.h

@ -10,7 +10,7 @@
class WebThreeStubClient : public jsonrpc::Client
{
public:
WebThreeStubClient(jsonrpc::IClientConnector &conn) : jsonrpc::Client(conn) {}
WebThreeStubClient(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
std::string web3_sha3(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
@ -52,7 +52,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_setListening(const bool& param1) throw (jsonrpc::JsonRpcException)
bool eth_setListening(bool param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -72,7 +72,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_setMining(const bool& param1) throw (jsonrpc::JsonRpcException)
bool eth_setMining(bool param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -122,7 +122,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException)
bool eth_setDefaultBlock(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -233,7 +233,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException)
Json::Value eth_blockByNumber(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -243,7 +243,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException)
Json::Value eth_transactionByHash(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -254,7 +254,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException)
Json::Value eth_transactionByNumber(int param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -265,7 +265,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException)
Json::Value eth_uncleByHash(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -276,7 +276,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException)
Json::Value eth_uncleByNumber(int param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -347,7 +347,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException)
bool eth_uninstallFilter(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -357,7 +357,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_changed(const int& param1) throw (jsonrpc::JsonRpcException)
Json::Value eth_changed(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -367,7 +367,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_filterLogs(const int& param1) throw (jsonrpc::JsonRpcException)
Json::Value eth_filterLogs(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -515,7 +515,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool shh_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException)
bool shh_uninstallFilter(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -525,7 +525,7 @@ class WebThreeStubClient : public jsonrpc::Client
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value shh_changed(const int& param1) throw (jsonrpc::JsonRpcException)
Json::Value shh_changed(int param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
@ -537,4 +537,4 @@ class WebThreeStubClient : public jsonrpc::Client
}
};
#endif //JSONRPC_CPP_WEBTHREESTUBCLIENT_H_
#endif //JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_

5
third/CMakeLists.txt

@ -32,8 +32,11 @@ eth_add_executable(${EXECUTABLE}
add_dependencies(${EXECUTABLE} BuildInfo.h)
target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Widgets)
target_link_libraries(${EXECUTABLE} Qt5::WebKit)
target_link_libraries(${EXECUTABLE} Qt5::WebKitWidgets)
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} qwebthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} ethcore)

20
third/MainWin.cpp

@ -40,6 +40,7 @@
#include <libethereum/EthereumHost.h>
#include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include "BuildInfo.h"
#include "MainWin.h"
#include "ui_Main.h"
@ -118,20 +119,24 @@ Main::Main(QWidget *parent) :
m_web3.reset(new WebThreeDirect("Third", getDataDir() + "/Third", false, {"eth", "shh"}, NetworkPreferences(), networkConfig));
m_web3->connect(Host::pocHost());
m_server = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(m_qwebConnector, *web3(), keysAsVector(m_myKeys)));
m_httpConnector.reset(new jsonrpc::HttpServer(8080));
m_server.reset(new WebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys)));
// m_server = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(m_httpConnector, *web3(), keysAsVector(m_myKeys)));
m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening();
connect(ui->webView, &QWebView::loadStarted, [this]()
{
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_qweb = new QWebThree(this);
auto qweb = m_qweb;
m_qwebConnector.setQWeb(qweb);
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, [f, this]()
{
f->disconnect();
f->addToJavaScriptWindowObject("env", this, QWebFrame::QtOwnership);
f->evaluateJavaScript(contentsOfQResource(":/js/bignumber.min.js"));
f->evaluateJavaScript(contentsOfQResource(":/js/webthree.js"));
f->evaluateJavaScript(contentsOfQResource(":/js/setup.js"));
});
});
connect(ui->webView, &QWebView::loadFinished, [=]()
@ -163,7 +168,6 @@ Main::~Main()
{
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
m_qweb->clientDieing();
writeSettings();
}

8
third/MainWin.h

@ -30,7 +30,6 @@
#include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h>
#include <libethereum/State.h>
#include <libqwebthree/QWebThree.h>
namespace Ui {
class Main;
@ -47,6 +46,10 @@ class WhisperHost;
}
}
namespace jsonrpc {
class HttpServer;
}
class QQuickView;
class WebThreeStubServer;
@ -136,7 +139,6 @@ private:
QNetworkAccessManager m_webCtrl;
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
std::unique_ptr<WebThreeStubServer> m_server;
QWebThreeConnector m_qwebConnector;
QWebThree* m_qweb = nullptr;
};

Loading…
Cancel
Save