Browse Source

Merge branch 'develop' into crypto

Conflicts:
	libdevcrypto/CryptoPP.h
	libdevcrypto/EC.cpp
cl-refactor
subtly 10 years ago
parent
commit
e48c5ce042
  1. 257
      alethzero/Main.ui
  2. 227
      alethzero/MainWin.cpp
  3. 5
      alethzero/MainWin.h
  4. 6
      libdevcore/CMakeLists.txt
  5. 2
      libdevcore/Common.cpp
  6. 2
      libdevcore/FixedHash.h
  7. 3
      libdevcrypto/All.h
  8. 4
      libdevcrypto/Common.cpp
  9. 12
      libdevcrypto/EC.cpp
  10. 2
      libethereum/Client.h
  11. 19
      libevmface/CMakeLists.txt
  12. 3
      libp2p/Host.cpp
  13. 2
      libp2p/Host.h
  14. 12
      libpyserpent/pyserpent.cpp
  15. 175
      libqethereum/QEthereum.cpp
  16. 29
      libqethereum/QEthereum.h
  17. 32
      libserpent/compiler.cpp
  18. 12
      libserpent/funcs.cpp
  19. 6
      libserpent/funcs.h
  20. 4
      libserpent/opcodes.h
  21. 24
      libserpent/parser.cpp
  22. 60
      libserpent/rewriter.cpp
  23. 3
      libserpent/rewriter.h
  24. 6
      libserpent/util.cpp
  25. 58
      libsolidity/AST.cpp
  26. 10
      libsolidity/AST.h
  27. 6
      libsolidity/ASTPrinter.cpp
  28. 7
      libsolidity/BaseTypes.h
  29. 27
      libsolidity/CMakeLists.txt
  30. 5
      libsolidity/Exceptions.h
  31. 26
      libsolidity/NameAndTypeResolver.cpp
  32. 29
      libsolidity/Parser.cpp
  33. 5
      libsolidity/Parser.h
  34. 2
      libsolidity/Scope.cpp
  35. 93
      libsolidity/SourceReferenceFormatter.cpp
  36. 48
      libsolidity/SourceReferenceFormatter.h
  37. 3
      libsolidity/Types.cpp
  38. 16
      libwhisper/Common.cpp
  39. 6
      libwhisper/Common.h
  40. 30
      libwhisper/Interface.h
  41. 18
      libwhisper/Message.cpp
  42. 16
      libwhisper/Message.h
  43. 44
      libwhisper/WhisperHost.cpp
  44. 20
      libwhisper/WhisperHost.h
  45. 205
      sc/cmdline.cpp
  46. 17
      solc/CMakeLists.txt
  47. 81
      solc/main.cpp
  48. 3
      third/MainWin.cpp
  49. 6
      windows/LibEthereum.vcxproj
  50. 18
      windows/LibEthereum.vcxproj.filters

257
alethzero/Main.ui

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1711</width>
<height>1138</height>
<width>1617</width>
<height>1371</height>
</rect>
</property>
<property name="windowTitle">
@ -116,7 +116,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1711</width>
<width>1617</width>
<height>25</height>
</rect>
</property>
@ -204,11 +204,18 @@
<addaction name="debugStepBackInto"/>
<addaction name="debugStepBackOut"/>
</widget>
<widget class="QMenu" name="menuWhispe">
<property name="title">
<string>&amp;Whisper</string>
</property>
<addaction name="newIdentity"/>
</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="menu_Help"/>
</widget>
@ -1514,6 +1521,242 @@ font-size: 14pt</string>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_14">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Whisper</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_14">
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="4">
<widget class="QSpinBox" name="shhWork">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Topic</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="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<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>
</item>
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<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>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="post">
<property name="text">
<string>Post</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TTL</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QComboBox" name="shhFrom">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="shhTo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" rowspan="2">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>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="2" column="1">
<widget class="QSpinBox" name="shhTtl">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>259200</number>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label5_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Work to Prove</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_15">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Active Whispers</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_15">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>0</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="QListWidget" name="whispers">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="quit">
<property name="text">
<string>&amp;Quit</string>
@ -1789,6 +2032,9 @@ font-size: 14pt</string>
</property>
</action>
<action name="importKeyFile">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Claim Ether Presale &amp;Wallet...</string>
</property>
@ -1798,6 +2044,11 @@ font-size: 14pt</string>
<string>Go!</string>
</property>
</action>
<action name="newIdentity">
<property name="text">
<string>New Identity</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

227
alethzero/MainWin.cpp

@ -146,11 +146,13 @@ Main::Main(QWidget *parent) :
auto qeth = m_ethereum;
auto qshh = m_whisper;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh));
connect(m_whisper, SIGNAL(idsChanged()), this, SLOT(refreshWhisper()));
});
connect(ui->webView, &QWebView::loadFinished, [=]()
{
m_ethereum->poll();
m_whisper->poll();
});
connect(ui->webView, &QWebView::titleChanged, [=]()
@ -331,8 +333,6 @@ void Main::load(QString _s)
}
}
// env.load("/home/gav/eth/init.eth")
void Main::on_loadJS_triggered()
{
QString f = QFileDialog::getOpenFileName(this, "Load Javascript", QString(), "Javascript (*.js);;All files (*)");
@ -387,6 +387,17 @@ void Main::eval(QString const& _js)
ui->jsConsole->setHtml(s);
}
static Public stringToPublic(QString const& _a)
{
string sn = _a.toStdString();
if (_a.size() == sizeof(Public) * 2)
return Public(fromHex(_a.toStdString()));
else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x"))
return Public(fromHex(_a.mid(2).toStdString()));
else
return Public();
}
QString Main::pretty(dev::Address _a) const
{
h256 n;
@ -752,7 +763,6 @@ void Main::refreshNetwork()
{
auto ps = web3()->peers();
ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)");
ui->peers->clear();
ui->nodes->clear();
@ -995,12 +1005,15 @@ void Main::timerEvent(QTimerEvent*)
{
interval = 0;
refreshNetwork();
refreshWhispers();
}
else
interval += 100;
if (m_ethereum)
m_ethereum->poll();
if (m_whisper)
m_whisper->poll();
for (auto const& i: m_handlers)
if (ethereum()->checkWatch(i.first))
@ -1382,6 +1395,112 @@ void Main::on_destination_currentTextChanged()
// updateFee();
}
static bytes dataFromText(QString _s)
{
bytes ret;
while (_s.size())
{
QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?");
QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?");
QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?");
if (r.exactMatch(_s))
{
for (auto i: r.cap(2))
ret.push_back((byte)i.toLatin1());
if (r.cap(1) != "$")
for (int i = r.cap(2).size(); i < 32; ++i)
ret.push_back(0);
else
ret.push_back(0);
_s = r.cap(3);
}
else if (d.exactMatch(_s))
{
u256 v(d.cap(2).toStdString());
if (d.cap(6) == "szabo")
v *= dev::eth::szabo;
else if (d.cap(5) == "finney")
v *= dev::eth::finney;
else if (d.cap(4) == "ether")
v *= dev::eth::ether;
bytes bs = dev::toCompactBigEndian(v);
if (d.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
ret.push_back(0);
for (auto b: bs)
ret.push_back(b);
_s = d.cap(7);
}
else if (h.exactMatch(_s))
{
bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString());
if (h.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
ret.push_back(0);
for (auto b: bs)
ret.push_back(b);
_s = h.cap(5);
}
else
_s = _s.mid(1);
}
return ret;
}
static shh::Topic topicFromText(QString _s)
{
shh::BuildTopic ret;
while (_s.size())
{
QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?");
QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?");
QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?");
bytes part;
if (r.exactMatch(_s))
{
for (auto i: r.cap(2))
part.push_back((byte)i.toLatin1());
if (r.cap(1) != "$")
for (int i = r.cap(2).size(); i < 32; ++i)
part.push_back(0);
else
part.push_back(0);
_s = r.cap(3);
}
else if (d.exactMatch(_s))
{
u256 v(d.cap(2).toStdString());
if (d.cap(6) == "szabo")
v *= dev::eth::szabo;
else if (d.cap(5) == "finney")
v *= dev::eth::finney;
else if (d.cap(4) == "ether")
v *= dev::eth::ether;
bytes bs = dev::toCompactBigEndian(v);
if (d.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
part.push_back(0);
for (auto b: bs)
part.push_back(b);
_s = d.cap(7);
}
else if (h.exactMatch(_s))
{
bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString());
if (h.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
part.push_back(0);
for (auto b: bs)
part.push_back(b);
_s = h.cap(5);
}
else
_s = _s.mid(1);
ret.shift(part);
}
return ret;
}
void Main::on_data_textChanged()
{
m_pcWarp.clear();
@ -1436,54 +1555,7 @@ void Main::on_data_textChanged()
}
else
{
m_data.clear();
QString s = ui->data->toPlainText();
while (s.size())
{
QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?");
QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?");
QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?");
if (r.exactMatch(s))
{
for (auto i: r.cap(2))
m_data.push_back((byte)i.toLatin1());
if (r.cap(1) != "$")
for (int i = r.cap(2).size(); i < 32; ++i)
m_data.push_back(0);
else
m_data.push_back(0);
s = r.cap(3);
}
else if (d.exactMatch(s))
{
u256 v(d.cap(2).toStdString());
if (d.cap(6) == "szabo")
v *= dev::eth::szabo;
else if (d.cap(5) == "finney")
v *= dev::eth::finney;
else if (d.cap(4) == "ether")
v *= dev::eth::ether;
bytes bs = dev::toCompactBigEndian(v);
if (d.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
m_data.push_back(0);
for (auto b: bs)
m_data.push_back(b);
s = d.cap(7);
}
else if (h.exactMatch(s))
{
bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString());
if (h.cap(1) != "$")
for (auto i = bs.size(); i < 32; ++i)
m_data.push_back(0);
for (auto b: bs)
m_data.push_back(b);
s = h.cap(5);
}
else
s = s.mid(1);
}
m_data = dataFromText(ui->data->toPlainText());
ui->code->setHtml(QString::fromStdString(dev::memDump(m_data, 8, true)));
if (ethereum()->codeAt(fromString(ui->destination->currentText()), 0).size())
{
@ -2012,6 +2084,59 @@ void Main::updateDebugger()
}
}
void Main::on_post_clicked()
{
shh::Message m;
m.setTo(stringToPublic(ui->shhTo->currentText()));
m.setPayload(dataFromText(ui->shhData->toPlainText()));
Public f = stringToPublic(ui->shhFrom->currentText());
Secret from;
if (m_whisper->ids().count(f))
from = m_whisper->ids().at(f);
whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value()));
}
void Main::on_newIdentity_triggered()
{
m_whisper->makeIdentity();
}
void Main::refreshWhisper()
{
ui->shhFrom->clear();
for (auto i: m_whisper->ids())
ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref())));
}
void Main::refreshWhispers()
{
ui->whispers->clear();
for (auto const& w: whisper()->all())
{
shh::Envelope const& e = w.second;
shh::Message m;
for (pair<Public, Secret> const& i: m_whisper->ids())
if (!!(m = e.open(i.second)))
break;
if (!m)
m = e.open();
QString msg;
if (m.from())
// Good message.
msg = QString("%1->%2: %3").arg(m.from() ? m.from().abridged().c_str() : "?").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str());
else if (m)
// Maybe message.
msg = QString("%1->%2: %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "?").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str());
time_t ex = e.expiry();
QString t(ctime(&ex));
t.chop(1);
QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg);
ui->whispers->addItem(item);
}
}
// extra bits needed to link on VS
#ifdef _MSC_VER

5
alethzero/MainWin.h

@ -149,6 +149,10 @@ private slots:
void on_turboMining_triggered();
void on_go_triggered();
void on_importKeyFile_triggered();
void on_post_clicked();
void on_newIdentity_triggered();
void refreshWhisper();
signals:
void poll();
@ -202,6 +206,7 @@ private:
void refreshNetwork();
void refreshMining();
void refreshWhispers();
void refreshAll();
void refreshPending();

6
libdevcore/CMakeLists.txt

@ -19,8 +19,6 @@ endif()
include_directories(..)
target_link_libraries(${EXECUTABLE} devcore)
if("${TARGET_PLATFORM}" STREQUAL "w64")
include_directories(/usr/x86_64-w64-mingw32/include/cryptopp)
target_link_libraries(${EXECUTABLE} boost_system-mt-s)
@ -37,7 +35,9 @@ elseif (APPLE)
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
elseif (UNIX)
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY})
find_package(Boost 1.53 REQUIRED COMPONENTS thread system)
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY})
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
else ()
target_link_libraries(${EXECUTABLE} boost_thread)

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.7.5";
char const* Version = "0.7.6";
}

2
libdevcore/FixedHash.h

@ -59,7 +59,7 @@ public:
FixedHash() { m_data.fill(0); }
/// Construct from another hash, filling with zeroes or cropping as necessary.
template <unsigned M> FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; }
template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; }
/// Convert from the corresponding arithmetic type.
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }

3
libdevcrypto/All.h

@ -1,9 +1,12 @@
#pragma once
#include "Common.h"
#include "CryptoPP.h"
#include "EC.h"
#include "FileSystem.h"
#include "MemoryDB.h"
#include "OverlayDB.h"
#include "SHA3.h"
#include "SHA3MAC.h"
#include "TrieCommon.h"
#include "TrieDB.h"

4
libdevcrypto/Common.cpp

@ -144,7 +144,9 @@ Public dev::recover(Signature _sig, h256 _message)
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
#endif
return *(Public const*)&(pubkey[1]);
Public ret;
memcpy(&ret, &(pubkey[1]), sizeof(Public));
return ret;
}
inline h256 kFromMessage(h256 _msg, h256 _priv)

12
libdevcrypto/EC.cpp

@ -49,9 +49,9 @@ void crypto::encrypt(Public const& _key, bytes& io_cipher)
size_t plen = io_cipher.size();
bytes c;
c.resize(e.CiphertextLength(plen));
// todo: use StringSource with _plain as input and output.
// todo: use StringSource with io_cipher as input and output.
e.Encrypt(pp::PRNG, io_cipher.data(), plen, c.data());
bzero(io_cipher.data(), io_cipher.size());
memset(io_cipher.data(), 0, io_cipher.size());
io_cipher = std::move(c);
}
@ -62,9 +62,13 @@ void crypto::decrypt(Secret const& _k, bytes& io_text)
size_t clen = io_text.size();
bytes p;
p.resize(d.MaxPlaintextLength(io_text.size()));
// todo: use StringSource with _c as input and output.
// todo: use StringSource with io_text as input and output.
DecodingResult r = d.Decrypt(pp::PRNG, io_text.data(), clen, p.data());
assert(r.messageLength);
if (!r.isValidCoding)
{
io_text.clear();
return;
}
io_text.resize(r.messageLength);
io_text = std::move(p);
}

2
libethereum/Client.h

@ -285,7 +285,7 @@ private:
State m_preMine; ///< The present state of the client.
State m_postMine; ///< The state of the client which we're mining (i.e. it'll have all the rewards added).
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::vector<Miner> m_miners;
mutable boost::shared_mutex x_miners;

19
libevmface/CMakeLists.txt

@ -17,25 +17,6 @@ include_directories(..)
target_link_libraries(${EXECUTABLE} devcore)
if("${TARGET_PLATFORM}" STREQUAL "w64")
target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s)
target_link_libraries(${EXECUTABLE} iphlpapi)
target_link_libraries(${EXECUTABLE} ws2_32)
target_link_libraries(${EXECUTABLE} mswsock)
target_link_libraries(${EXECUTABLE} shlwapi)
elseif (APPLE)
# Latest mavericks boost libraries only come with -mt
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
elseif (UNIX)
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY})
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
else ()
target_link_libraries(${EXECUTABLE} boost_thread)
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
endif ()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

3
libp2p/Host.cpp

@ -143,6 +143,9 @@ void Host::stop()
void Host::quit()
{
// called to force io_service to kill any remaining tasks it might have -
// such tasks may involve socket reads from Capabilities that maintain references
// to resources we're about to free.
stop();
m_ioService.reset();
// m_acceptor & m_socket are DANGEROUS now.

2
libp2p/Host.h

@ -203,7 +203,7 @@ private:
/// This won't touch alter the blockchain.
virtual void doWork();
std::shared_ptr<Node> noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId = h256());
std::shared_ptr<Node> noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId = NodeId());
Nodes potentialPeers(RangeMask<unsigned> const& _known);
std::string m_clientVersion; ///< Our version string.

12
libpyserpent/pyserpent.cpp

@ -120,11 +120,15 @@ std::vector<Node> cppifyNodeList(PyObject* o) {
}
PYMETHOD(ps_compile, FROMSTR, compile, pyifyString)
PYMETHOD(ps_compile_chunk, FROMSTR, compileChunk, pyifyString)
PYMETHOD(ps_compile_to_lll, FROMSTR, compileToLLL, pyifyNode)
PYMETHOD(ps_compile_chunk_to_lll, FROMSTR, compileChunkToLLL, pyifyNode)
PYMETHOD(ps_compile_lll, FROMNODE, compileLLL, pyifyString)
PYMETHOD(ps_parse, FROMSTR, parseSerpent, pyifyNode)
PYMETHOD(ps_rewrite, FROMNODE, rewrite, pyifyNode)
PYMETHOD(ps_rewrite_chunk, FROMNODE, rewriteChunk, pyifyNode)
PYMETHOD(ps_pretty_compile, FROMSTR, prettyCompile, pyifyNodeList)
PYMETHOD(ps_pretty_compile_chunk, FROMSTR, prettyCompileChunk, pyifyNodeList)
PYMETHOD(ps_pretty_compile_lll, FROMNODE, prettyCompileLLL, pyifyNodeList)
PYMETHOD(ps_serialize, FROMLIST, serialize, pyifyString)
PYMETHOD(ps_deserialize, FROMSTR, deserialize, pyifyNodeList)
@ -134,16 +138,24 @@ PYMETHOD(ps_parse_lll, FROMSTR, parseLLL, pyifyNode)
static PyMethodDef PyextMethods[] = {
{"compile", ps_compile, METH_VARARGS,
"Compile code."},
{"compile_chunk", ps_compile_chunk, METH_VARARGS,
"Compile code chunk (no wrappers)."},
{"compile_to_lll", ps_compile_to_lll, METH_VARARGS,
"Compile code to LLL."},
{"compile_chunk_to_lll", ps_compile_chunk_to_lll, METH_VARARGS,
"Compile code chunk to LLL (no wrappers)."},
{"compile_lll", ps_compile_lll, METH_VARARGS,
"Compile LLL to EVM."},
{"parse", ps_parse, METH_VARARGS,
"Parse serpent"},
{"rewrite", ps_rewrite, METH_VARARGS,
"Rewrite parsed serpent to LLL"},
{"rewrite_chunk", ps_rewrite_chunk, METH_VARARGS,
"Rewrite parsed serpent to LLL (no wrappers)"},
{"pretty_compile", ps_pretty_compile, METH_VARARGS,
"Compile to EVM opcodes"},
{"pretty_compile_chunk", ps_pretty_compile_chunk, METH_VARARGS,
"Compile chunk to EVM opcodes (no wrappers)"},
{"pretty_compile_lll", ps_pretty_compile_lll, METH_VARARGS,
"Compile LLL to EVM opcodes"},
{"serialize", ps_serialize, METH_VARARGS,

175
libqethereum/QEthereum.cpp

@ -5,6 +5,8 @@
#include <liblll/Compiler.h>
#include <libethereum/Client.h>
#include <libethereum/EthereumHost.h>
#include <libwhisper/Message.h>
#include <libwhisper/WhisperHost.h>
#include "QEthereum.h"
using namespace std;
using namespace dev;
@ -21,7 +23,7 @@ dev::bytes toBytes(QString const& _s)
else
{
// Binary
cwarn << "THIS FUNCTIONALITY IS DEPRECATED. DO NOT ASSUME ASCII/BINARY-STRINGS WILL BE ACCEPTED. USE eth.fromAscii().";
cwarn << "'" << _s.toStdString() << "': Unrecognised format for number/hash. USE eth.fromAscii() if you mean to convert from ASCII.";
return asBytes(_s);
}
}
@ -558,37 +560,184 @@ void QWhisper::faceDieing()
}
void QWhisper::send(QString /*dev::Address*/ _dest, QString /*ev::KeyPair*/ _from, QString /*dev::h256 const&*/ _topic, QString /*dev::bytes const&*/ _payload)
static shh::Message toMessage(QString _json)
{
(void)_dest;
(void)_from;
(void)_topic;
(void)_payload;
shh::Message ret;
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("from"))
ret.setFrom(toPublic(f["from"].toString()));
if (f.contains("to"))
ret.setTo(toPublic(f["to"].toString()));
if (f.contains("payload"))
ret.setPayload(toBytes(f["payload"].toString()));
return ret;
}
unsigned QWhisper::newWatch(QString _json)
static shh::Envelope toSealed(QString _json, shh::Message const& _m, Secret _from)
{
(void)_json;
return 0;
unsigned ttl = 50;
unsigned workToProve = 50;
shh::BuildTopic bt;
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("ttl"))
ttl = f["ttl"].toInt();
if (f.contains("workToProve"))
workToProve = f["workToProve"].toInt();
if (f.contains("topic"))
{
if (f["topic"].isString())
bt.shift(asBytes(padded(f["topic"].toString(), 32)));
else if (f["topic"].isArray())
for (auto i: f["topic"].toArray())
bt.shift(asBytes(padded(i.toString(), 32)));
}
return _m.seal(_from, bt, ttl, workToProve);
}
QString QWhisper::watchMessages(unsigned _w)
void QWhisper::doPost(QString _json)
{
shh::Message m = toMessage(_json);
Secret from;
if (m.from() && m_ids.count(m.from()))
{
cwarn << "Silently signing message from identity" << m.from().abridged() << ": User validation hook goes here.";
// TODO: insert validification hook here.
from = m_ids[m.from()];
}
face()->inject(toSealed(_json, m, from));
}
static pair<shh::TopicMask, Public> toWatch(QString _json)
{
shh::BuildTopicMask bt(shh::BuildTopicMask::Empty);
Public to;
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("to"))
to = toPublic(f["to"].toString());
if (f.contains("topic"))
{
if (f["topic"].isString())
bt.shift(asBytes(padded(f["topic"].toString(), 32)));
else if (f["topic"].isArray())
for (auto i: f["topic"].toArray())
if (i.isString())
bt.shift(asBytes(padded(i.toString(), 32)));
else
bt.shift();
}
return make_pair(bt.toTopicMask(), to);
}
// _json contains
// topic: the topic as an array of components, some may be null.
// to: specifies the id to which the message is encrypted. null if broadcast.
unsigned QWhisper::newWatch(QString _json)
{
(void)_w;
return "";
auto w = toWatch(_json);
auto ret = face()->installWatch(w.first);
m_watches.insert(make_pair(ret, w.second));
return ret;
}
void QWhisper::killWatch(unsigned _w)
{
(void)_w;
face()->uninstallWatch(_w);
m_watches.erase(_w);
}
void QWhisper::clearWatches()
{
for (auto i: m_watches)
face()->uninstallWatch(i.first);
m_watches.clear();
}
static QString toJson(h256 const& _h, shh::Envelope const& _e, shh::Message const& _m)
{
QJsonObject v;
v["hash"] = toQJS(_h);
v["expiry"] = (int)_e.expiry();
v["sent"] = (int)_e.sent();
v["ttl"] = (int)_e.ttl();
v["workProved"] = (int)_e.workProved();
v["topic"] = toQJS(_e.topic());
v["payload"] = toQJS(_m.payload());
v["from"] = toQJS(_m.from());
v["to"] = toQJS(_m.to());
return QString::fromUtf8(QJsonDocument(v).toJson());
}
QString QWhisper::watchMessages(unsigned _w)
{
QString ret = "[";
auto wit = m_watches.find(_w);
if (wit == m_watches.end())
{
cwarn << "watchMessages called with invalid watch id" << _w;
return "";
}
Public p = wit->second;
if (!p || m_ids.count(p))
for (h256 const& h: face()->watchMessages(_w))
{
auto e = face()->envelope(h);
shh::Message m;
if (p)
{
cwarn << "Silently decrypting message from identity" << p.abridged() << ": User validation hook goes here.";
m = e.open(m_ids[p]);
}
else
m = e.open();
ret.append((ret == "[" ? "" : ",") + toJson(h, e, m));
}
return ret + "]";
}
QString QWhisper::newIdentity()
{
return toQJS(makeIdentity());
}
Public QWhisper::makeIdentity()
{
KeyPair kp = KeyPair::create();
m_ids[kp.pub()] = kp.sec();
emit idsChanged();
return kp.pub();
}
void QWhisper::poll()
{
for (auto const& w: m_watches)
if (!w.second || m_ids.count(w.second))
for (h256 const& h: face()->checkWatch(w.first))
{
auto e = face()->envelope(h);
shh::Message m;
if (w.second)
{
cwarn << "Silently decrypting message from identity" << w.second.abridged() << ": User validation hook goes here.";
m = e.open(m_ids[w.second]);
if (!m)
continue;
}
else
m = e.open();
emit watchChanged(w.first, toJson(h, e, m));
}
}
// extra bits needed to link on VS

29
libqethereum/QEthereum.h

@ -59,8 +59,9 @@ template <unsigned N> dev::FixedHash<N> toFixed(QString const& _s)
template <unsigned N> inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>> toInt(QString const& _s);
inline dev::Address toAddress(QString const& _s) { return toFixed<20>(_s); }
inline dev::Secret toSecret(QString const& _s) { return toFixed<32>(_s); }
inline dev::Address toAddress(QString const& _s) { return toFixed<sizeof(dev::Address)>(_s); }
inline dev::Public toPublic(QString const& _s) { return toFixed<sizeof(dev::Public)>(_s); }
inline dev::Secret toSecret(QString const& _s) { return toFixed<sizeof(dev::Secret)>(_s); }
inline dev::u256 toU256(QString const& _s) { return toInt<32>(_s); }
template <unsigned S> QString toQJS(dev::FixedHash<S> const& _h) { return QString::fromStdString("0x" + toHex(_h.ref())); }
@ -225,14 +226,18 @@ public:
Q_INVOKABLE QWhisper* self() { return this; }
/// Basic message send.
Q_INVOKABLE void send(QString /*dev::Address*/ _dest, QString /*ev::KeyPair*/ _from, QString /*dev::h256 const&*/ _topic, QString /*dev::bytes const&*/ _payload);
Q_INVOKABLE void doPost(QString _json);
// Watches interface
Q_INVOKABLE QString newIdentity();
// Watches interface
Q_INVOKABLE unsigned newWatch(QString _json);
Q_INVOKABLE QString watchMessages(unsigned _w);
Q_INVOKABLE void killWatch(unsigned _w);
void clearWatches();
Q_INVOKABLE void clearWatches();
Q_INVOKABLE QString watchMessages(unsigned _w);
dev::Public makeIdentity();
std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; }
public slots:
/// Check to see if anything has changed, fire off signals if so.
@ -240,11 +245,14 @@ public slots:
void poll();
signals:
void watchChanged(unsigned _w);
void watchChanged(unsigned _w, QString _envelopeJson);
void idsChanged();
private:
std::weak_ptr<dev::shh::Interface> m_face;
std::vector<unsigned> m_watches;
std::map<unsigned, dev::Public> m_watches;
std::map<dev::Public, dev::Secret> m_ids;
};
// TODO: add p2p object
@ -269,8 +277,9 @@ private:
if (_shh) \
{ \
_frame->addToJavaScriptWindowObject("_web3_dot_shh", _shh, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("_web3_dot_shh.makeWatch = function(a) { var ww = _web3_dot_shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { _web3_dot_shh.killWatch(w); }; ret.changed = function(f) { _web3_dot_shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(_web3_dot_shh.watchMessages(this.w)) }; return ret; }"); \
_frame->evaluateJavaScript("_web3_dot_shh.watch = function(a) { return _web3_dot_shh.makeWatch(JSON.stringify(a)) }"); \
_frame->evaluateJavaScript("_web3_dot_shh.makeWatch = function(json) { var ww = _web3_dot_shh.newWatch(json); var ret = { w: ww }; ret.uninstall = function() { _web3_dot_shh.killWatch(w); }; ret.arrived = function(f) { _web3_dot_shh.watchChanged.connect(function(nw, envelope) { if (nw == ww) f(JSON.parse(envelope)) }); var existing = JSON.parse(_web3_dot_shh.watchMessages(ww)); for (var e in existing) f(existing[e]) }; return ret; }"); \
_frame->evaluateJavaScript("_web3_dot_shh.watch = function(filter) { return _web3_dot_shh.makeWatch(JSON.stringify(filter)) }"); \
_frame->evaluateJavaScript("_web3_dot_shh.post = function(message) { return _web3_dot_shh.doPost(JSON.stringify(message)) }"); \
_frame->evaluateJavaScript("web3.shh = _web3_dot_shh"); \
} \
}

32
libserpent/compiler.cpp

@ -123,9 +123,10 @@ programData opcodeify(Node node,
token("$begincode"+symb+".endcode"+symb, m), token("DUP1", m),
token("$begincode"+symb, m), sub.code, token("CODECOPY", m),
token("$endcode"+symb, m), token("JUMP", m),
token("~begincode"+symb, m), code, token("~endcode"+symb, m)
token("~begincode"+symb, m), code, token("~endcode"+symb, m),
token("JUMPDEST", m)
};
return pd(sub.aux, multiToken(nodelist, 10, m), 1);
return pd(sub.aux, multiToken(nodelist, 11, m), 1);
}
// Stack variables
if (node.val == "with") {
@ -171,9 +172,9 @@ programData opcodeify(Node node,
cond.code,
token("$endif"+symb, m), token("JUMPI", m),
action.code,
token("~endif"+symb, m)
token("~endif"+symb, m), token("JUMPDEST", m)
};
return pd(aux, multiToken(nodelist, 5, m), 0);
return pd(aux, multiToken(nodelist, 6, m), 0);
}
// 3-part conditional
else if (node.val == "if" && node.args.size() == 3) {
@ -190,13 +191,15 @@ programData opcodeify(Node node,
if (elsed.outs > outs) elsed.code = popwrap(elsed.code);
Node nodelist[] = {
ifd.code,
token("NOT", m), token("$else"+symb, m), token("JUMPI", m),
token("NOT", m),
token("$else"+symb, m), token("JUMPI", m),
thend.code,
token("$endif"+symb, m), token("JUMP", m), token("~else"+symb, m),
token("$endif"+symb, m), token("JUMP", m),
token("~else"+symb, m), token("JUMPDEST", m),
elsed.code,
token("~endif"+symb, m)
token("~endif"+symb, m), token("JUMPDEST", m)
};
return pd(aux, multiToken(nodelist, 10, m), outs);
return pd(aux, multiToken(nodelist, 12, m), outs);
}
// While (rewritten to this in rewrites)
else if (node.val == "until") {
@ -207,13 +210,14 @@ programData opcodeify(Node node,
err("Condition of while/until loop has arity 0", m);
if (action.outs) action.code = popwrap(action.code);
Node nodelist[] = {
token("~beg"+symb, m),
token("~beg"+symb, m), token("JUMPDEST", m),
cond.code,
token("$end"+symb, m), token("JUMPI", m),
action.code,
token("$beg"+symb, m), token("JUMP", m), token("~end"+symb, m)
token("$beg"+symb, m), token("JUMP", m),
token("~end"+symb, m), token("JUMPDEST", m)
};
return pd(aux, multiToken(nodelist, 8, m));
return pd(aux, multiToken(nodelist, 10, m));
}
// Memory allocations
else if (node.val == "alloc") {
@ -298,7 +302,7 @@ Node finalize(programData c) {
Metadata m = c.code.metadata;
// If we are using both alloc and variables, we need to pre-zfill
// some memory
if (c.aux.allocUsed && c.aux.vars.size() > 0) {
if ((c.aux.allocUsed || c.aux.calldataUsed) && c.aux.vars.size() > 0) {
Node nodelist[] = {
token("0", m),
token(unsignedToDecimal(c.aux.vars.size() * 32 - 1)),
@ -309,8 +313,8 @@ Node finalize(programData c) {
// If msg.data is being used as an array, then we need to copy it
if (c.aux.calldataUsed) {
Node nodelist[] = {
token("MSIZE", m), token("CALLDATASIZE", m), token("MSIZE", m),
token("0", m), token("CALLDATACOPY", m),
token("MSIZE", m), token("CALLDATASIZE", m), token("0", m),
token("MSIZE", m), token("CALLDATACOPY", m),
token(c.aux.vars["'msg.data"], m), token("MSTORE", m)
};
bottom.push_back(multiToken(nodelist, 7, m));

12
libserpent/funcs.cpp

@ -14,6 +14,10 @@ Node compileToLLL(std::string input) {
return rewrite(parseSerpent(input));
}
Node compileChunkToLLL(std::string input) {
return rewriteChunk(parseSerpent(input));
}
std::string compile(std::string input) {
return compileLLL(compileToLLL(input));
}
@ -21,3 +25,11 @@ std::string compile(std::string input) {
std::vector<Node> prettyCompile(std::string input) {
return prettyCompileLLL(compileToLLL(input));
}
std::string compileChunk(std::string input) {
return compileLLL(compileChunkToLLL(input));
}
std::vector<Node> prettyCompileChunk(std::string input) {
return prettyCompileLLL(compileChunkToLLL(input));
}

6
libserpent/funcs.h

@ -24,6 +24,12 @@
Node compileToLLL(std::string input);
Node compileChunkToLLL(std::string input);
std::string compile(std::string input);
std::vector<Node> prettyCompile(std::string input);
std::string compileChunk(std::string input);
std::vector<Node> prettyCompileChunk(std::string input);

4
libserpent/opcodes.h

@ -72,11 +72,11 @@ Mapping mapping[] = {
Mapping("PC", 0x5a, 0, 1),
Mapping("MSIZE", 0x5b, 0, 1),
Mapping("GAS", 0x5c, 0, 1),
Mapping("JUMPDEST", 0x5d, 0, 0),
Mapping("CREATE", 0xf0, 3, 1),
Mapping("CALL", 0xf1, 7, 1),
Mapping("RETURN", 0xf2, 2, 0),
Mapping("POST", 0xf3, 5, 0),
Mapping("CALL_STATELESS", 0xf4, 7, 1),
Mapping("CALL_CODE", 0xf3, 7, 1),
Mapping("SUICIDE", 0xff, 1, 0),
Mapping("---END---", 0x00, 0, 0),
};

24
libserpent/parser.cpp

@ -32,7 +32,7 @@ int toktype(Node tok) {
if (v == "(" || v == "[" || v == "{") return LPAREN;
else if (v == ")" || v == "]" || v == "}") return RPAREN;
else if (v == ",") return COMMA;
else if (v == "!" || v == "not") return UNARY_OP;
else if (v == "!" || v == "not" || v == "neg") return UNARY_OP;
else if (precedence(tok) >= 0) return BINARY_OP;
if (tok.val[0] != '"' && tok.val[0] != '\'') {
for (unsigned i = 0; i < tok.val.length(); i++) {
@ -91,17 +91,19 @@ std::vector<Node> shuntingYard(std::vector<Node> tokens) {
// If binary op, keep popping from stack while higher bedmas precedence
else if (toktyp == BINARY_OP) {
if (tok.val == "-" && prevtyp != ALPHANUM && prevtyp != RPAREN) {
oq.push_back(token("0", tok.metadata));
stack.push_back(token("neg", tok.metadata));
}
int prec = precedence(tok);
while (stack.size()
&& (toktype(stack.back()) == BINARY_OP
|| toktype(stack.back()) == UNARY_OP)
&& precedence(stack.back()) <= prec) {
oq.push_back(stack.back());
stack.pop_back();
else {
int prec = precedence(tok);
while (stack.size()
&& (toktype(stack.back()) == BINARY_OP
|| toktype(stack.back()) == UNARY_OP)
&& precedence(stack.back()) <= prec) {
oq.push_back(stack.back());
stack.pop_back();
}
stack.push_back(tok);
}
stack.push_back(tok);
}
// Comma means finish evaluating the argument
else if (toktyp == COMMA) {
@ -153,10 +155,10 @@ Node treefy(std::vector<Node> stream) {
else if (typ == RPAREN) {
std::vector<Node> args;
while (1) {
if (!oq.size()) err("Bracket without matching", tok.metadata);
if (toktype(oq.back()) == LPAREN) break;
args.push_back(oq.back());
oq.pop_back();
if (!oq.size()) err("Bracket without matching", tok.metadata);
}
oq.pop_back();
args.push_back(oq.back());

60
libserpent/rewriter.cpp

@ -17,9 +17,7 @@ std::string valid[][3] = {
{ "alloc", "1", "1" },
{ "array", "1", "1" },
{ "call", "2", "4" },
{ "call_stateless", "2", "4" },
{ "post", "4", "5" },
{ "postcall", "3", "4" },
{ "call_code", "2", "4" },
{ "create", "1", "4" },
{ "msg", "4", "6" },
{ "msg_stateless", "4", "6" },
@ -28,6 +26,8 @@ std::string valid[][3] = {
{ "sha3", "1", "2" },
{ "return", "1", "2" },
{ "inset", "1", "1" },
{ "min", "2", "2" },
{ "max", "2", "2" },
{ "array_lit", "0", tt256 },
{ "seq", "0", tt256 },
{ "---END---", "", "" } //Keep this line at the end of the list
@ -70,6 +70,14 @@ std::string macros[][2] = {
"(!= $a $b)",
"(not (eq $a $b))"
},
{
"(min a b)",
"(with $1 a (with $2 b (if (lt $1 $2) $1 $2)))"
},
{
"(max a b)",
"(with $1 a (with $2 b (if (lt $1 $2) $2 $1)))"
},
{
"(if $cond $do (else $else))",
"(if $cond $do $else)"
@ -134,22 +142,6 @@ std::string macros[][2] = {
"(send $to $value)",
"(call (sub (gas) 25) $to $value 0 0 0 0)"
},
{
"(post $gas $to $value $datain $datainsz)",
"(~post $gas $to $value $datain (mul $datainsz 32))"
},
{
"(post $gas $to $value $datain)",
"(seq (set $1 $datain) (~post $gas $to $value (ref $1) 32))"
},
{
"(postcall $gas $to $datain)",
"(post $gas $to 0 $datain)",
},
{
"(postcall $gas $to $datain $datainsz)",
"(post $gas $to 0 $datain $datainsz)",
},
{
"(send $gas $to $value)",
"(call $gas $to $value 0 0 0 0)"
@ -229,32 +221,32 @@ std::string macros[][2] = {
},
{
"(msg $gas $to $val $inp $inpsz $outsz)",
"(with $1 (mul 32 $outsz) (with $2 (alloc (get $1)) (call $gas $to $val $inp (mul 32 $inpsz) (get $2) (get $1)) (get $2)))"
"(with $1 (mul 32 $outsz) (with $2 (alloc (get $1)) (seq (call $gas $to $val $inp (mul 32 $inpsz) (get $2) (get $1)) (get $2))))"
},
// Call stateless and msg stateless
{
"(call_stateless $f $dataval)",
"(msg_stateless (sub (gas) 45) $f 0 $dataval)"
"(call_code $f $dataval)",
"(msg_code (sub (gas) 45) $f 0 $dataval)"
},
{
"(call_stateless $f $inp $inpsz)",
"(msg_stateless (sub (gas) 25) $f 0 $inp $inpsz)"
"(call_code $f $inp $inpsz)",
"(msg_code (sub (gas) 25) $f 0 $inp $inpsz)"
},
{
"(call_stateless $f $inp $inpsz $outsz)",
"(with $1 $outsz (with $2 (alloc (mul 32 (get $1))) (seq (call_stateless (sub (gas) (add 25 (get $1))) $f 0 $inp (mul 32 $inpsz) (get $2) (mul 32 (get $1))) (get $2))))"
"(call_code $f $inp $inpsz $outsz)",
"(with $1 $outsz (with $2 (alloc (mul 32 (get $1))) (seq (call_code (sub (gas) (add 25 (get $1))) $f 0 $inp (mul 32 $inpsz) (get $2) (mul 32 (get $1))) (get $2))))"
},
{
"(msg_stateless $gas $to $val $inp $inpsz)",
"(seq (call_stateless $gas $to $val $inp (mul 32 $inpsz) (ref $1) 32) (get $1))"
"(msg_code $gas $to $val $inp $inpsz)",
"(seq (call_code $gas $to $val $inp (mul 32 $inpsz) (ref $1) 32) (get $1))"
},
{
"(msg_stateless $gas $to $val $dataval)",
"(seq (set $1 $dataval) (call_stateless $gas $to $val (ref $1) 32 (ref $2) 32) (get $2))"
"(msg_code $gas $to $val $dataval)",
"(seq (set $1 $dataval) (call_code $gas $to $val (ref $1) 32 (ref $2) 32) (get $2))"
},
{
"(msg_stateless $gas $to $val $inp $inpsz $outsz)",
"(with $1 (mul 32 $outsz) (with $2 (alloc (get $1)) (call_stateless $gas $to $val $inp (mul 32 $inpsz) (get $2) (get $1)) (get $2)))"
"(msg_code $gas $to $val $inp $inpsz $outsz)",
"(with $1 (mul 32 $outsz) (with $2 (alloc (get $1)) (call_code $gas $to $val $inp (mul 32 $inpsz) (get $2) (get $1)) (get $2)))"
},
// Wrappers
{
@ -561,4 +553,8 @@ Node rewrite(Node inp) {
return optimize(apply_rules(validate(preprocess(inp))));
}
Node rewriteChunk(Node inp) {
return optimize(apply_rules(validate(inp)));
}
using namespace std;

3
libserpent/rewriter.h

@ -10,4 +10,7 @@
// Applies rewrite rules
Node rewrite(Node inp);
// Applies rewrite rules adding without wrapper
Node rewriteChunk(Node inp);
#endif

6
libserpent/util.cpp

@ -137,7 +137,7 @@ std::string strToNumeric(std::string inp) {
}
else if (inp.substr(0,2) == "0x") {
for (unsigned i = 2; i < inp.length(); i++) {
int dig = std::string("0123456789abcdef").find(inp[i]);
int dig = std::string("0123456789abcdef0123456789ABCDEF").find(inp[i]) % 16;
if (dig < 0) return "";
o = decimalAdd(decimalMul(o,"16"), unsignedToDecimal(dig));
}
@ -219,8 +219,8 @@ void err(std::string errtext, Metadata met) {
std::string err = "Error (file \"" + met.file + "\", line " +
unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) +
"): " + errtext;
std::cerr << err << "\n";
throw(err);
std::cerr << err << "\n";
throw(err);
}
//Bin to hex

58
libsolidity/AST.cpp

@ -248,12 +248,16 @@ void Literal::accept(ASTVisitor& _visitor)
_visitor.endVisit(*this);
}
TypeError ASTNode::createTypeError(std::string const& _description)
{
return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description);
}
void Statement::expectType(Expression& _expression, const Type& _expectedType)
{
_expression.checkTypeRequirements();
if (!_expression.getType()->isImplicitlyConvertibleTo(_expectedType))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Type not implicitly convertible "
"to expected type."));
BOOST_THROW_EXCEPTION(_expression.createTypeError("Type not implicitly convertible to expected type."));
//@todo provide more information to the exception
}
@ -287,11 +291,10 @@ void Break::checkTypeRequirements()
void Return::checkTypeRequirements()
{
BOOST_ASSERT(m_returnParameters != nullptr);
BOOST_ASSERT(m_returnParameters);
if (m_returnParameters->getParameters().size() != 1)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Different number of arguments in "
"return statement than in returns "
"declaration."));
BOOST_THROW_EXCEPTION(createTypeError("Different number of arguments in return statement "
"than in returns declaration."));
// this could later be changed such that the paramaters type is an anonymous struct type,
// but for now, we only allow one return parameter
expectType(*m_expression, *m_returnParameters->getParameters().front()->getType());
@ -327,7 +330,7 @@ void Assignment::checkTypeRequirements()
{
// complex assignment
if (!m_type->acceptsBinaryOperator(Token::AssignmentToBinaryOp(m_assigmentOperator)))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Operator not compatible with type."));
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type."));
}
}
@ -337,7 +340,7 @@ void UnaryOperation::checkTypeRequirements()
m_subExpression->checkTypeRequirements();
m_type = m_subExpression->getType();
if (m_type->acceptsUnaryOperator(m_operator))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Unary operator not compatible with type."));
BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type."));
}
void BinaryOperation::checkTypeRequirements()
@ -349,7 +352,7 @@ void BinaryOperation::checkTypeRequirements()
else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType()))
m_commonType = m_right->getType();
else
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("No common type found in binary operation."));
BOOST_THROW_EXCEPTION(createTypeError("No common type found in binary operation."));
if (Token::isCompareOp(m_operator))
m_type = std::make_shared<BoolType>();
else
@ -357,7 +360,7 @@ void BinaryOperation::checkTypeRequirements()
BOOST_ASSERT(Token::isBinaryOp(m_operator));
m_type = m_commonType;
if (!m_commonType->acceptsBinaryOperator(m_operator))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Operator not compatible with type."));
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type."));
}
}
@ -371,15 +374,14 @@ void FunctionCall::checkTypeRequirements()
if (category == Type::Category::TYPE)
{
TypeType const* type = dynamic_cast<TypeType const*>(&expressionType);
BOOST_ASSERT(type != nullptr);
BOOST_ASSERT(type);
//@todo for structs, we have to check the number of arguments to be equal to the
// number of non-mapping members
if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("More than one argument for "
"explicit type conersion."));
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for "
"explicit type conersion."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type->getActualType()))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Explicit type conversion not "
"allowed."));
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type->getActualType();
}
else if (category == Type::Category::FUNCTION)
@ -388,16 +390,14 @@ void FunctionCall::checkTypeRequirements()
// and then ask if that is implicitly convertible to the struct represented by the
// function parameters
FunctionType const* function = dynamic_cast<FunctionType const*>(&expressionType);
BOOST_ASSERT(function != nullptr);
BOOST_ASSERT(function);
FunctionDefinition const& fun = function->getFunction();
std::vector<ASTPointer<VariableDeclaration>> const& parameters = fun.getParameters();
if (parameters.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Wrong argument count for "
"function call."));
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameters[i]->getType()))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Invalid type for argument in "
"function call."));
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
// @todo actually the return type should be an anonymous struct,
// but we change it to the type of the first return value until we have structs
if (fun.getReturnParameterList()->getParameters().empty())
@ -406,9 +406,7 @@ void FunctionCall::checkTypeRequirements()
m_type = fun.getReturnParameterList()->getParameters().front()->getType();
}
else
{
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Type does not support invocation."));
}
BOOST_THROW_EXCEPTION(createTypeError("Type does not support invocation."));
}
void MemberAccess::checkTypeRequirements()
@ -425,7 +423,7 @@ void IndexAccess::checkTypeRequirements()
void Identifier::checkTypeRequirements()
{
BOOST_ASSERT(m_referencedDeclaration != nullptr);
BOOST_ASSERT(m_referencedDeclaration);
//@todo these dynamic casts here are not really nice...
// is i useful to have an AST visitor here?
// or can this already be done in NameAndTypeResolver?
@ -435,24 +433,24 @@ void Identifier::checkTypeRequirements()
// var y = x;
// the type of x is not yet determined.
VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration);
if (variable != nullptr)
if (variable)
{
if (!variable->getType())
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Variable referenced before type "
"could be determined."));
BOOST_THROW_EXCEPTION(createTypeError("Variable referenced before type "
"could be determined."));
m_type = variable->getType();
return;
}
//@todo can we unify these with TypeName::toType()?
StructDefinition* structDef = dynamic_cast<StructDefinition*>(m_referencedDeclaration);
if (structDef != nullptr)
if (structDef)
{
// note that we do not have a struct type here
m_type = std::make_shared<TypeType>(std::make_shared<StructType>(*structDef));
return;
}
FunctionDefinition* functionDef = dynamic_cast<FunctionDefinition*>(m_referencedDeclaration);
if (functionDef != nullptr)
if (functionDef)
{
// a function reference is not a TypeType, because calling a TypeType converts to the type.
// Calling a function (e.g. function(12), otherContract.function(34)) does not do a type
@ -461,7 +459,7 @@ void Identifier::checkTypeRequirements()
return;
}
ContractDefinition* contractDef = dynamic_cast<ContractDefinition*>(m_referencedDeclaration);
if (contractDef != nullptr)
if (contractDef)
{
m_type = std::make_shared<TypeType>(std::make_shared<ContractType>(*contractDef));
return;

10
libsolidity/AST.h

@ -22,16 +22,16 @@
#pragma once
#include <boost/noncopyable.hpp>
#include <string>
#include <vector>
#include <memory>
#include <boost/noncopyable.hpp>
#include <libsolidity/ASTForward.h>
#include <libsolidity/BaseTypes.h>
#include <libsolidity/Token.h>
#include <libsolidity/Types.h>
#include <libsolidity/Exceptions.h>
namespace dev
{
@ -57,6 +57,10 @@ public:
Location const& getLocation() const { return m_location; }
/// Creates a @ref TypeError exception and decorates it with the location of the node and
/// the given description
TypeError createTypeError(std::string const& _description);
private:
Location m_location;
};
@ -165,7 +169,7 @@ public:
Declaration(_location, _name), m_typeName(_type) {}
virtual void accept(ASTVisitor& _visitor) override;
bool isTypeGivenExplicitly() const { return m_typeName.get() != nullptr; }
bool isTypeGivenExplicitly() const { return bool(m_typeName); }
TypeName* getTypeName() const { return m_typeName.get(); }
//! Returns the declared or inferred type. Can be an empty pointer if no type was explicitly

6
libsolidity/ASTPrinter.cpp

@ -253,7 +253,7 @@ bool ASTPrinter::visit(ElementaryTypeNameExpression& _node)
bool ASTPrinter::visit(Literal& _node)
{
char const* tokenString = Token::toString(_node.getToken());
if (tokenString == nullptr)
if (!tokenString)
tokenString = "[no token]";
writeLine(std::string("Literal, token: ") + tokenString + " value: " + _node.getValue());
printType(_node);
@ -417,7 +417,7 @@ void ASTPrinter::printSourcePart(ASTNode const& _node)
{
Location const& location(_node.getLocation());
*m_ostream << getIndentation() << " Source: |"
<< m_source.substr(location.start, location.end - location.start) << "|\n";
<< m_source.substr(location.start, location.end - location.start) << "|" << std::endl;
}
}
@ -436,7 +436,7 @@ std::string ASTPrinter::getIndentation() const
void ASTPrinter::writeLine(std::string const& _line)
{
*m_ostream << getIndentation() << _line << '\n';
*m_ostream << getIndentation() << _line << std::endl;
}
}

7
libsolidity/BaseTypes.h

@ -22,6 +22,7 @@
#pragma once
#include <ostream>
namespace dev
{
@ -41,5 +42,11 @@ struct Location
int end;
};
/// Stream output for Location (used e.g. in boost exceptions).
inline std::ostream& operator<<(std::ostream& _out, Location const& _location)
{
return _out << "[" << _location.start << "," << _location.end << ")";
}
}
}

27
libsolidity/CMakeLists.txt

@ -16,33 +16,8 @@ file(GLOB HEADERS "*.h")
include_directories(..)
target_link_libraries(${EXECUTABLE} evmface)
target_link_libraries(${EXECUTABLE} devcore)
if("${TARGET_PLATFORM}" STREQUAL "w64")
target_link_libraries(${EXECUTABLE} boost_system-mt-s)
target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s)
target_link_libraries(${EXECUTABLE} iphlpapi)
target_link_libraries(${EXECUTABLE} ws2_32)
target_link_libraries(${EXECUTABLE} mswsock)
target_link_libraries(${EXECUTABLE} shlwapi)
elseif (APPLE)
# Latest mavericks boost libraries only come with -mt
target_link_libraries(${EXECUTABLE} boost_system-mt)
target_link_libraries(${EXECUTABLE} boost_thread-mt)
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
elseif (UNIX)
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY})
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY})
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
else ()
target_link_libraries(${EXECUTABLE} boost_system)
target_link_libraries(${EXECUTABLE} boost_thread)
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
endif ()
target_link_libraries(${EXECUTABLE} evmface)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

5
libsolidity/Exceptions.h

@ -22,7 +22,9 @@
#pragma once
#include <string>
#include <libdevcore/Exceptions.h>
#include <libsolidity/BaseTypes.h>
namespace dev
{
@ -33,5 +35,8 @@ struct ParserError: virtual Exception {};
struct TypeError: virtual Exception {};
struct DeclarationError: virtual Exception {};
typedef boost::error_info<struct tag_sourcePosition, int> errinfo_sourcePosition;
typedef boost::error_info<struct tag_sourceLocation, Location> errinfo_sourceLocation;
}
}

26
libsolidity/NameAndTypeResolver.cpp

@ -129,15 +129,17 @@ void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _node)
void DeclarationRegistrationHelper::closeCurrentScope()
{
BOOST_ASSERT(m_currentScope != nullptr);
BOOST_ASSERT(m_currentScope);
m_currentScope = m_currentScope->getOuterScope();
}
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
{
BOOST_ASSERT(m_currentScope != nullptr);
BOOST_ASSERT(m_currentScope);
if (!m_currentScope->registerDeclaration(_declaration))
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Identifier already declared."));
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation())
<< errinfo_comment("Identifier already declared."));
//@todo the exception should also contain the location of the first declaration
if (_opensScope)
enterNewSubScope(_declaration);
}
@ -153,14 +155,14 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable)
{
// endVisit because the internal type needs resolving if it is a user defined type
// or mapping
if (_variable.getTypeName() != nullptr)
if (_variable.getTypeName())
_variable.setType(_variable.getTypeName()->toType());
// otherwise we have a "var"-declaration whose type is resolved by the first assignment
}
bool ReferencesResolver::visit(Return& _return)
{
BOOST_ASSERT(m_returnParameters != nullptr);
BOOST_ASSERT(m_returnParameters);
_return.setFunctionReturnParameters(*m_returnParameters);
return true;
}
@ -174,12 +176,13 @@ bool ReferencesResolver::visit(Mapping&)
bool ReferencesResolver::visit(UserDefinedTypeName& _typeName)
{
Declaration* declaration = m_resolver.getNameFromCurrentScope(_typeName.getName());
if (declaration == nullptr)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Undeclared identifier."));
if (!declaration)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_typeName.getLocation())
<< errinfo_comment("Undeclared identifier."));
StructDefinition* referencedStruct = dynamic_cast<StructDefinition*>(declaration);
//@todo later, contracts are also valid types
if (referencedStruct == nullptr)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Identifier does not name a type name."));
if (!referencedStruct)
BOOST_THROW_EXCEPTION(_typeName.createTypeError("Identifier does not name a type name."));
_typeName.setReferencedStruct(*referencedStruct);
return false;
}
@ -187,8 +190,9 @@ bool ReferencesResolver::visit(UserDefinedTypeName& _typeName)
bool ReferencesResolver::visit(Identifier& _identifier)
{
Declaration* declaration = m_resolver.getNameFromCurrentScope(_identifier.getName());
if (declaration == nullptr)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Undeclared identifier."));
if (!declaration)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation())
<< errinfo_comment("Undeclared identifier."));
_identifier.setReferencedDeclaration(*declaration);
return false;
}

29
libsolidity/Parser.cpp

@ -106,7 +106,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
expectToken(Token::SEMICOLON);
}
else
throwExpectationError("Function, variable or struct declaration expected.");
BOOST_THROW_EXCEPTION(createParserError("Function, variable or struct declaration expected."));
}
nodeFactory.markEndPosition();
expectToken(Token::RBRACE);
@ -184,7 +184,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
else if (token == Token::VAR)
{
if (!_allowVar)
throwExpectationError("Expected explicit type name.");
BOOST_THROW_EXCEPTION(createParserError("Expected explicit type name."));
m_scanner->next();
}
else if (token == Token::MAPPING)
@ -198,7 +198,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
type = nodeFactory.createNode<UserDefinedTypeName>(expectIdentifierToken());
}
else
throwExpectationError("Expected type name");
BOOST_THROW_EXCEPTION(createParserError("Expected type name"));
return type;
}
@ -208,7 +208,7 @@ ASTPointer<Mapping> Parser::parseMapping()
expectToken(Token::MAPPING);
expectToken(Token::LPAREN);
if (!Token::isElementaryTypeName(m_scanner->getCurrentToken()))
throwExpectationError("Expected elementary type name for mapping key type");
BOOST_THROW_EXCEPTION(createParserError("Expected elementary type name for mapping key type"));
ASTPointer<ElementaryTypeName> keyType;
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(m_scanner->getCurrentToken());
m_scanner->next();
@ -481,7 +481,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
}
else
{
throwExpectationError("Expected primary expression.");
BOOST_THROW_EXCEPTION(createParserError("Expected primary expression."));
return ASTPointer<Expression>(); // this is not reached
}
break;
@ -507,7 +507,7 @@ std::vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
void Parser::expectToken(Token::Value _value)
{
if (m_scanner->getCurrentToken() != _value)
throwExpectationError(std::string("Expected token ") + std::string(Token::getName(_value)));
BOOST_THROW_EXCEPTION(createParserError(std::string("Expected token ") + std::string(Token::getName(_value))));
m_scanner->next();
}
@ -515,7 +515,7 @@ Token::Value Parser::expectAssignmentOperator()
{
Token::Value op = m_scanner->getCurrentToken();
if (!Token::isAssignmentOp(op))
throwExpectationError(std::string("Expected assignment operator"));
BOOST_THROW_EXCEPTION(createParserError("Expected assignment operator"));
m_scanner->next();
return op;
}
@ -523,7 +523,7 @@ Token::Value Parser::expectAssignmentOperator()
ASTPointer<ASTString> Parser::expectIdentifierToken()
{
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
throwExpectationError("Expected identifier");
BOOST_THROW_EXCEPTION(createParserError("Expected identifier"));
return getLiteralAndAdvance();
}
@ -534,18 +534,9 @@ ASTPointer<ASTString> Parser::getLiteralAndAdvance()
return identifier;
}
void Parser::throwExpectationError(std::string const& _description)
ParserError Parser::createParserError(std::string const& _description) const
{
//@todo put some of this stuff into ParserError
int line, column;
std::tie(line, column) = m_scanner->translatePositionToLineColumn(getPosition());
std::stringstream buf;
buf << "Solidity parser error: " << _description
<< " at line " << (line + 1)
<< ", column " << (column + 1) << "\n"
<< m_scanner->getLineAtPosition(getPosition()) << "\n"
<< std::string(column, ' ') << "^";
BOOST_THROW_EXCEPTION(ParserError() << errinfo_comment(buf.str()));
return ParserError() << errinfo_sourcePosition(getPosition()) << errinfo_comment(_description);
}

5
libsolidity/Parser.h

@ -73,9 +73,12 @@ private:
Token::Value expectAssignmentOperator();
ASTPointer<ASTString> expectIdentifierToken();
ASTPointer<ASTString> getLiteralAndAdvance();
void throwExpectationError(std::string const& _description);
/// @}
/// Creates a @ref ParserError exception and annotates it with the current position and the
/// given @a _description.
ParserError createParserError(std::string const& _description) const;
std::shared_ptr<Scanner> m_scanner;
};

2
libsolidity/Scope.cpp

@ -41,7 +41,7 @@ Declaration* Scope::resolveName(ASTString const& _name, bool _recursive) const
auto result = m_declarations.find(_name);
if (result != m_declarations.end())
return result->second;
if (_recursive && m_outerScope != nullptr)
if (_recursive && m_outerScope)
return m_outerScope->resolveName(_name, true);
return nullptr;
}

93
libsolidity/SourceReferenceFormatter.cpp

@ -0,0 +1,93 @@
/*
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/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Formatting functions for errors referencing positions and locations in the source.
*/
#include <libsolidity/SourceReferenceFormatter.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Exceptions.h>
namespace dev
{
namespace solidity
{
void SourceReferenceFormatter::printSourceLocation(std::ostream& _stream,
Location const& _location,
Scanner const& _scanner)
{
int startLine;
int startColumn;
std::tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start);
_stream << "starting at line " << (startLine + 1) << ", column " << (startColumn + 1) << "\n";
int endLine;
int endColumn;
std::tie(endLine, endColumn) = _scanner.translatePositionToLineColumn(_location.end);
if (startLine == endLine)
{
_stream << _scanner.getLineAtPosition(_location.start) << std::endl
<< std::string(startColumn, ' ') << "^";
if (endColumn > startColumn + 2)
_stream << std::string(endColumn - startColumn - 2, '-');
if (endColumn > startColumn + 1)
_stream << "^";
_stream << std::endl;
}
else
_stream << _scanner.getLineAtPosition(_location.start) << std::endl
<< std::string(startColumn, ' ') << "^\n"
<< "Spanning multiple lines.\n";
}
void SourceReferenceFormatter::printSourcePosition(std::ostream& _stream,
int _position,
const Scanner& _scanner)
{
int line;
int column;
std::tie(line, column) = _scanner.translatePositionToLineColumn(_position);
_stream << "at line " << (line + 1) << ", column " << (column + 1) << std::endl
<< _scanner.getLineAtPosition(_position) << std::endl
<< std::string(column, ' ') << "^" << std::endl;
}
void SourceReferenceFormatter::printExceptionInformation(std::ostream& _stream,
Exception const& _exception,
std::string const& _name,
Scanner const& _scanner)
{
_stream << _name;
if (std::string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description;
if (int const* position = boost::get_error_info<errinfo_sourcePosition>(_exception))
{
_stream << " ";
printSourcePosition(_stream, *position, _scanner);
}
if (Location const* location = boost::get_error_info<errinfo_sourceLocation>(_exception))
{
_stream << " ";
printSourceLocation(_stream, *location, _scanner);
}
}
}
}

48
libsolidity/SourceReferenceFormatter.h

@ -0,0 +1,48 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Formatting functions for errors referencing positions and locations in the source.
*/
#pragma once
#include <ostream>
#include <libsolidity/BaseTypes.h>
namespace dev
{
class Exception; // forward
namespace solidity
{
class Scanner; // forward
struct SourceReferenceFormatter
{
public:
static void printSourceLocation(std::ostream& _stream, Location const& _location, Scanner const& _scanner);
static void printSourcePosition(std::ostream& _stream, int _position, Scanner const& _scanner);
static void printExceptionInformation(std::ostream& _stream, Exception const& _exception,
std::string const& _name, Scanner const& _scanner);
};
}
}

3
libsolidity/Types.cpp

@ -51,6 +51,7 @@ std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
return std::make_shared<BoolType>();
else
BOOST_ASSERT(false); // @todo add other tyes
return std::shared_ptr<Type>();
}
std::shared_ptr<Type> Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName)
@ -89,9 +90,9 @@ std::shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(std::string con
IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier):
m_bits(_bits), m_modifier(_modifier)
{
BOOST_ASSERT(_bits > 0 && _bits <= 256 && _bits % 8 == 0);
if (isAddress())
_bits = 160;
BOOST_ASSERT(_bits > 0 && _bits <= 256 && _bits % 8 == 0);
}
bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const

16
libwhisper/Common.cpp

@ -43,10 +43,16 @@ h256 TopicFilter::sha3() const
TopicMask BuildTopicMask::toTopicMask() const
{
TopicMask ret;
for (auto i = 0; i < 32; ++i)
{
ret.first[i] = m_parts[i * m_parts.size() / 32][i];
ret.second[i] = m_parts[i * m_parts.size() / 32] ? 255 : 0;
}
if (m_parts.size())
for (auto i = 0; i < 32; ++i)
{
ret.first[i] = m_parts[i * m_parts.size() / 32][i];
ret.second[i] = m_parts[i * m_parts.size() / 32] ? 255 : 0;
}
return ret;
}
/*
web3.shh.watch({}).arrived(function(m) { env.note("New message:\n"+JSON.stringify(m)); })
k = web3.shh.newIdentity()
web3.shh.post({from: k, topic: web3.fromAscii("test"), payload: web3.fromAscii("Hello world!")})
*/

6
libwhisper/Common.h

@ -64,6 +64,7 @@ using Topic = h256;
class BuildTopic
{
public:
BuildTopic() {}
template <class T> BuildTopic(T const& _t) { shift(_t); }
template <class T> BuildTopic& shift(T const& _r) { return shiftBytes(RLPStream().append(_r).out()); }
@ -75,8 +76,6 @@ public:
Topic toTopic() const { Topic ret; for (auto i = 0; i < 32; ++i) ret[i] = m_parts[i * m_parts.size() / 32][i]; return ret; }
protected:
BuildTopic() {}
BuildTopic& shiftBytes(bytes const& _b);
h256s m_parts;
@ -105,7 +104,10 @@ private:
class BuildTopicMask: BuildTopic
{
public:
enum EmptyType { Empty };
BuildTopicMask() { shift(); }
BuildTopicMask(EmptyType) {}
template <class T> BuildTopicMask(T const& _t) { shift(_t); }
template <class T> BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; }

30
libwhisper/Interface.h

@ -43,6 +43,8 @@ namespace shh
Topic mask;
};*/
class Watch;
struct InstalledFilter
{
InstalledFilter(TopicFilter const& _f): filter(_f) {}
@ -73,13 +75,14 @@ public:
virtual void uninstallWatch(unsigned _watchId) = 0;
virtual h256s peekWatch(unsigned _watchId) const = 0;
virtual h256s checkWatch(unsigned _watchId) = 0;
virtual h256s watchMessages(unsigned _watchId) = 0;
virtual Envelope envelope(h256 _m) const = 0;
void post(bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_topic, _ttl, _workToProve)); }
void post(Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_to, _topic, _ttl, _workToProve)); }
void post(Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_to, _topic, _ttl, _workToProve)); }
void post(Secret _from, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _topic, _ttl, _workToProve)); }
void post(Secret _from, Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _to, _topic, _ttl, _workToProve)); }
void post(Secret _from, Public _to, bytes const& _payload, Topic _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_from, _to, _topic, _ttl, _workToProve)); }
};
struct WatshhChannel: public dev::LogChannel { static const char* name() { return "shh"; } static const int verbosity = 1; };
@ -87,9 +90,11 @@ struct WatshhChannel: public dev::LogChannel { static const char* name() { retur
}
}
/*
namespace std { void swap(shh::Watch& _a, shh::Watch& _b); }
namespace std { void swap(dev::shh::Watch& _a, dev::shh::Watch& _b); }
namespace dev
{
namespace shh
{
@ -99,28 +104,29 @@ class Watch: public boost::noncopyable
public:
Watch() {}
Watch(Whisper& _c, h256 _f): m_c(&_c), m_id(_c.installWatch(_f)) {}
Watch(Whisper& _c, TopicFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {}
Watch(Interface& _c, TopicMask const& _f): m_c(&_c), m_id(_c.installWatch(_f)) {}
Watch(Interface& _c, TopicFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {}
~Watch() { if (m_c) m_c->uninstallWatch(m_id); }
bool check() { return m_c ? m_c->checkWatch(m_id) : false; }
bool peek() { return m_c ? m_c->peekWatch(m_id) : false; }
h256s check() { return m_c ? m_c->checkWatch(m_id) : h256s(); }
h256s peek() { return m_c ? m_c->peekWatch(m_id) : h256s(); }
private:
Whisper* m_c;
Interface* m_c;
unsigned m_id;
};
}
}
namespace shh
namespace std
{
inline void swap(shh::Watch& _a, shh::Watch& _b)
inline void swap(dev::shh::Watch& _a, dev::shh::Watch& _b)
{
swap(_a.m_c, _b.m_c);
swap(_a.m_id, _b.m_id);
}
}
*/

18
libwhisper/Message.cpp

@ -34,18 +34,18 @@ Message::Message(Envelope const& _e, Secret const& _s)
if (_s)
if (!decrypt(_s, &(_e.data()), b))
return;
populate(_s ? b : _e.data());
m_to = KeyPair(_s).pub();
if (populate(_s ? b : _e.data()))
m_to = KeyPair(_s).pub();
}
catch (...) // Invalid secret? TODO: replace ... with InvalidSecret
{
}
}
void Message::populate(bytes const& _data)
bool Message::populate(bytes const& _data)
{
if (!_data.size())
return;
return false;
byte flags = _data[0];
if (!!(flags & ContainsSignature) && _data.size() > sizeof(Signature) + 1) // has a signature
@ -54,13 +54,16 @@ void Message::populate(bytes const& _data)
h256 h = sha3(payload);
Signature const& sig = *(Signature const*)&(_data[1 + payload.size()]);
m_from = recover(sig, h);
if (!m_from)
return false;
m_payload = payload.toBytes();
}
else
m_payload = bytesConstRef(&_data).cropped(1).toBytes();
return true;
}
Envelope Message::seal(Secret _from, Topic const& _topic, unsigned _ttl, unsigned _workToProve)
Envelope Message::seal(Secret _from, Topic const& _topic, unsigned _ttl, unsigned _workToProve) const
{
Envelope ret(time(0) + _ttl, _ttl, _topic);
@ -91,11 +94,6 @@ Message Envelope::open(Secret const& _s) const
return Message(*this, _s);
}
Message Envelope::open() const
{
return Message(*this);
}
unsigned Envelope::workProved() const
{
h256 d[2];

16
libwhisper/Message.h

@ -65,8 +65,7 @@ public:
Topic const& topic() const { return m_topic; }
bytes const& data() const { return m_data; }
Message open(Secret const& _s) const;
Message open() const;
Message open(Secret const& _s = Secret()) const;
unsigned workProved() const;
void proveWork(unsigned _ms);
@ -102,19 +101,22 @@ public:
Public to() const { return m_to; }
bytes const& payload() const { return m_payload; }
void setFrom(Public _from) { m_from = _from; }
void setTo(Public _to) { m_to = _to; }
void setPayload(bytes const& _payload) { m_payload = _payload; }
void setPayload(bytes&& _payload) { swap(m_payload, _payload); }
operator bool() const { return !!m_payload.size() || m_from || m_to; }
/// Turn this message into a ditributable Envelope.
Envelope seal(Secret _from, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50);
Envelope seal(Secret _from, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) const;
// Overloads for skipping _from or specifying _to.
Envelope seal(Topic const& _topic, unsigned _ttl = 50, unsigned _workToProve = 50) { return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope seal(Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope seal(Secret _from, Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(_from, _topic, _workToProve, _ttl); }
Envelope seal(Topic const& _topic, unsigned _ttl = 50, unsigned _workToProve = 50) const { return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope sealTo(Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(Secret(), _topic, _workToProve, _ttl); }
Envelope sealTo(Secret _from, Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(_from, _topic, _workToProve, _ttl); }
private:
void populate(bytes const& _data);
bool populate(bytes const& _data);
Public m_from;
Public m_to;

44
libwhisper/WhisperHost.cpp

@ -47,12 +47,19 @@ void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const
if (m_messages.count(_m))
{
UpgradeGuard ll(l);
m_messages.at(_m).streamOut(_s, true);
auto const& m = m_messages.at(_m);
cnote << "streamOut: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data());
m.streamOut(_s, true);
}
}
void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
{
cnote << "inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data());
if (_m.expiry() <= time(0))
return;
auto h = _m.sha3();
{
UpgradableGuard l(x_messages);
@ -60,9 +67,10 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
return;
UpgradeGuard ll(l);
m_messages[h] = _m;
m_expiryQueue[_m.expiry()] = h;
}
if (_p)
// if (_p)
{
Guard l(m_filterLock);
for (auto const& f: m_filters)
@ -107,6 +115,28 @@ unsigned WhisperHost::installWatch(shh::TopicFilter const& _f)
return installWatchOnId(h);
}
h256s WhisperHost::watchMessages(unsigned _watchId)
{
cleanup();
h256s ret;
auto wit = m_watches.find(_watchId);
if (wit == m_watches.end())
return ret;
TopicFilter f;
{
Guard l(m_filterLock);
auto fit = m_filters.find(wit->second.id);
if (fit == m_filters.end())
return ret;
f = fit->second.filter;
}
ReadGuard l(x_messages);
for (auto const& m: m_messages)
if (f.matches(m.second))
ret.push_back(m.first);
return ret;
}
void WhisperHost::uninstallWatch(unsigned _i)
{
cwatshh << "XXX" << _i;
@ -124,3 +154,13 @@ void WhisperHost::uninstallWatch(unsigned _i)
if (!--fit->second.refCount)
m_filters.erase(fit);
}
void WhisperHost::cleanup()
{
// remove old messages.
// should be called every now and again.
auto now = time(0);
WriteGuard l(x_messages);
for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it))
m_messages.erase(it->second);
}

20
libwhisper/WhisperHost.h

@ -48,16 +48,21 @@ public:
unsigned protocolVersion() const { return 0; }
virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr);
virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr) override;
using Interface::installWatch;
virtual unsigned installWatch(TopicFilter const& _filter);
virtual unsigned installWatchOnId(h256 _filterId);
virtual void uninstallWatch(unsigned _watchId);
virtual h256s peekWatch(unsigned _watchId) const { dev::Guard l(m_filterLock); try { return m_watches.at(_watchId).changes; } catch (...) { return h256s(); } }
virtual h256s checkWatch(unsigned _watchId) { dev::Guard l(m_filterLock); h256s ret; try { ret = m_watches.at(_watchId).changes; m_watches.at(_watchId).changes.clear(); } catch (...) {} return ret; }
virtual unsigned installWatch(TopicFilter const& _filter) override;
virtual unsigned installWatchOnId(h256 _filterId) override;
virtual void uninstallWatch(unsigned _watchId) override;
virtual h256s peekWatch(unsigned _watchId) const override { dev::Guard l(m_filterLock); try { return m_watches.at(_watchId).changes; } catch (...) { return h256s(); } }
virtual h256s checkWatch(unsigned _watchId) override { cleanup(); dev::Guard l(m_filterLock); h256s ret; try { ret = m_watches.at(_watchId).changes; m_watches.at(_watchId).changes.clear(); } catch (...) {} return ret; }
virtual h256s watchMessages(unsigned _watchId) override;
virtual Envelope envelope(h256 _m) const { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Envelope(); } }
virtual Envelope envelope(h256 _m) const override { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Envelope(); } }
std::map<h256, Envelope> all() const { ReadGuard l(x_messages); return m_messages; }
void cleanup();
private:
void streamMessage(h256 _m, RLPStream& _s) const;
@ -66,6 +71,7 @@ private:
mutable dev::SharedMutex x_messages;
std::map<h256, Envelope> m_messages;
std::map<unsigned, h256> m_expiryQueue;
mutable dev::Mutex m_filterLock;
std::map<h256, InstalledFilter> m_filters;

205
sc/cmdline.cpp

@ -3,100 +3,117 @@
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <libserpent/funcs.h>
#include <libdevcore/Exceptions.h>
int main(int argv, char** argc)
{
if (argv == 1)
{
std::cerr << "Must provide a command and arguments! Try parse, rewrite, compile, assemble\n";
return 0;
}
std::string flag = "";
std::string command = argc[1];
std::string input;
std::string secondInput;
if (std::string(argc[1]) == "-s")
{
flag = command.substr(1);
command = argc[2];
input = "";
std::string line;
while (std::getline(std::cin, line))
{
input += line + "\n";
}
secondInput = argv == 3 ? "" : argc[3];
}
else
{
if (argv == 2)
{
std::cerr << "Not enough arguments for serpent cmdline\n";
BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Not enough arguments for serpent cmdline"));
}
input = argc[2];
secondInput = argv == 3 ? "" : argc[3];
}
bool haveSec = secondInput.length() > 0;
if (command == "parse" || command == "parse_serpent")
std::cout << printAST(parseSerpent(input), haveSec) << "\n";
else if (command == "rewrite")
std::cout << printAST(rewrite(parseLLL(input, true)), haveSec) << "\n";
else if (command == "compile_to_lll")
std::cout << printAST(compileToLLL(input), haveSec) << "\n";
else if (command == "build_fragtree")
std::cout << printAST(buildFragmentTree(parseLLL(input, true))) << "\n";
else if (command == "compile_lll")
std::cout << binToHex(compileLLL(parseLLL(input, true))) << "\n";
else if (command == "dereference")
std::cout << printAST(dereference(parseLLL(input, true)), haveSec) <<"\n";
else if (command == "pretty_assemble")
std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n";
else if (command == "pretty_compile_lll")
std::cout << printTokens(prettyCompileLLL(parseLLL(input, true))) << "\n";
else if (command == "pretty_compile")
std::cout << printTokens(prettyCompile(input)) << "\n";
else if (command == "assemble")
std::cout << assemble(parseLLL(input, true)) << "\n";
else if (command == "serialize")
std::cout << binToHex(serialize(tokenize(input, Metadata(), false))) << "\n";
else if (command == "flatten")
std::cout << printTokens(flatten(parseLLL(input, true))) << "\n";
else if (command == "deserialize")
std::cout << printTokens(deserialize(hexToBin(input))) << "\n";
else if (command == "compile")
std::cout << binToHex(compile(input)) << "\n";
else if (command == "encode_datalist")
{
std::vector<Node> tokens = tokenize(input);
std::vector<std::string> o;
for (int i = 0; i < (int)tokens.size(); i++)
o.push_back(tokens[i].val);
std::cout << binToHex(encodeDatalist(o)) << "\n";
}
else if (command == "decode_datalist")
{
std::vector<std::string> o = decodeDatalist(hexToBin(input));
std::vector<Node> tokens;
for (int i = 0; i < (int)o.size(); i++)
tokens.push_back(token(o[i]));
std::cout << printTokens(tokens) << "\n";
}
else if (command == "tokenize")
std::cout << printTokens(tokenize(input));
else if (command == "biject")
{
if (argv == 3)
std::cerr << "Not enough arguments for biject\n";
int pos = decimalToUnsigned(secondInput);
std::vector<Node> n = prettyCompile(input);
if (pos >= (int)n.size())
std::cerr << "Code position too high\n";
Metadata m = n[pos].metadata;
std::cout << "Opcode: " << n[pos].val << ", file: " << m.file <<
", line: " << m.ln << ", char: " << m.ch << "\n";
}
int main(int argv, char** argc) {
if (argv == 1) {
std::cerr << "Must provide a command and arguments! Try parse, rewrite, compile, assemble\n";
return 0;
}
std::string flag = "";
std::string command = argc[1];
std::string input;
std::string secondInput;
if (std::string(argc[1]) == "-s") {
flag = command.substr(1);
command = argc[2];
input = "";
std::string line;
while (std::getline(std::cin, line)) {
input += line + "\n";
}
secondInput = argv == 3 ? "" : argc[3];
}
else {
if (argv == 2) {
std::cerr << "Not enough arguments for serpent cmdline\n";
throw(0);
}
input = argc[2];
secondInput = argv == 3 ? "" : argc[3];
}
bool haveSec = secondInput.length() > 0;
if (command == "parse" || command == "parse_serpent") {
std::cout << printAST(parseSerpent(input), haveSec) << "\n";
}
else if (command == "rewrite") {
std::cout << printAST(rewrite(parseLLL(input, true)), haveSec) << "\n";
}
else if (command == "compile_to_lll") {
std::cout << printAST(compileToLLL(input), haveSec) << "\n";
}
else if (command == "rewrite_chunk") {
std::cout << printAST(rewriteChunk(parseLLL(input, true)), haveSec) << "\n";
}
else if (command == "compile_chunk_to_lll") {
std::cout << printAST(compileChunkToLLL(input), haveSec) << "\n";
}
else if (command == "build_fragtree") {
std::cout << printAST(buildFragmentTree(parseLLL(input, true))) << "\n";
}
else if (command == "compile_lll") {
std::cout << binToHex(compileLLL(parseLLL(input, true))) << "\n";
}
else if (command == "dereference") {
std::cout << printAST(dereference(parseLLL(input, true)), haveSec) <<"\n";
}
else if (command == "pretty_assemble") {
std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n";
}
else if (command == "pretty_compile_lll") {
std::cout << printTokens(prettyCompileLLL(parseLLL(input, true))) << "\n";
}
else if (command == "pretty_compile") {
std::cout << printTokens(prettyCompile(input)) << "\n";
}
else if (command == "pretty_compile_chunk") {
std::cout << printTokens(prettyCompileChunk(input)) << "\n";
}
else if (command == "assemble") {
std::cout << assemble(parseLLL(input, true)) << "\n";
}
else if (command == "serialize") {
std::cout << binToHex(serialize(tokenize(input, Metadata(), false))) << "\n";
}
else if (command == "flatten") {
std::cout << printTokens(flatten(parseLLL(input, true))) << "\n";
}
else if (command == "deserialize") {
std::cout << printTokens(deserialize(hexToBin(input))) << "\n";
}
else if (command == "compile") {
std::cout << binToHex(compile(input)) << "\n";
}
else if (command == "compile_chunk") {
std::cout << binToHex(compileChunk(input)) << "\n";
}
else if (command == "encode_datalist") {
std::vector<Node> tokens = tokenize(input);
std::vector<std::string> o;
for (int i = 0; i < (int)tokens.size(); i++) {
o.push_back(tokens[i].val);
}
std::cout << binToHex(encodeDatalist(o)) << "\n";
}
else if (command == "decode_datalist") {
std::vector<std::string> o = decodeDatalist(hexToBin(input));
std::vector<Node> tokens;
for (int i = 0; i < (int)o.size(); i++)
tokens.push_back(token(o[i]));
std::cout << printTokens(tokens) << "\n";
}
else if (command == "tokenize") {
std::cout << printTokens(tokenize(input));
}
else if (command == "biject") {
if (argv == 3)
std::cerr << "Not enough arguments for biject\n";
int pos = decimalToUnsigned(secondInput);
std::vector<Node> n = prettyCompile(input);
if (pos >= (int)n.size())
std::cerr << "Code position too high\n";
Metadata m = n[pos].metadata;
std::cout << "Opcode: " << n[pos].val << ", file: " << m.file <<
", line: " << m.ln << ", char: " << m.ch << "\n";
}
}

17
solc/CMakeLists.txt

@ -9,23 +9,6 @@ set(EXECUTABLE solc)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} solidity)
target_link_libraries(${EXECUTABLE} devcore)
if ("${TARGET_PLATFORM}" STREQUAL "w64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
target_link_libraries(${EXECUTABLE} gcc)
target_link_libraries(${EXECUTABLE} gdi32)
target_link_libraries(${EXECUTABLE} ws2_32)
target_link_libraries(${EXECUTABLE} mswsock)
target_link_libraries(${EXECUTABLE} shlwapi)
target_link_libraries(${EXECUTABLE} iphlpapi)
target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s)
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
elseif (UNIX)
else ()
find_package(Threads REQUIRED)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
endif ()
install( TARGETS ${EXECUTABLE} DESTINATION bin )

81
solc/main.cpp

@ -1,3 +1,24 @@
/*
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/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Solidity commandline compiler.
*/
#include <string>
#include <iostream>
@ -9,21 +30,11 @@
#include <libsolidity/Parser.h>
#include <libsolidity/ASTPrinter.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Exceptions.h>
#include <libsolidity/SourceReferenceFormatter.h>
namespace dev
{
namespace solidity
{
ASTPointer<ContractDefinition> parseAST(std::string const& _source)
{
ASTPointer<Scanner> scanner = std::make_shared<Scanner>(CharStream(_source));
Parser parser;
return parser.parse(scanner);
}
}
} // end namespaces
using namespace dev;
using namespace solidity;
void help()
{
@ -57,28 +68,50 @@ int main(int argc, char** argv)
else
infile = argv[i];
}
std::string src;
std::string sourceCode;
if (infile.empty())
{
std::string s;
while (!std::cin.eof())
{
getline(std::cin, s);
src.append(s);
sourceCode.append(s);
}
}
else
sourceCode = asString(dev::contents(infile));
ASTPointer<ContractDefinition> ast;
std::shared_ptr<Scanner> scanner = std::make_shared<Scanner>(CharStream(sourceCode));
Parser parser;
try
{
src = dev::asString(dev::contents(infile));
ast = parser.parse(scanner);
}
std::cout << "Parsing..." << std::endl;
// @todo catch exception
dev::solidity::ASTPointer<dev::solidity::ContractDefinition> ast = dev::solidity::parseAST(src);
catch (ParserError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Parser error", *scanner);
return -1;
}
dev::solidity::NameAndTypeResolver resolver;
try
{
resolver.resolveNamesAndTypes(*ast.get());
}
catch (DeclarationError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Declaration error", *scanner);
return -1;
}
catch (TypeError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Type error", *scanner);
return -1;
}
std::cout << "Syntax tree for the contract:" << std::endl;
dev::solidity::ASTPrinter printer(ast, src);
dev::solidity::ASTPrinter printer(ast, sourceCode);
printer.print(std::cout);
std::cout << "Resolving identifiers..." << std::endl;
dev::solidity::NameAndTypeResolver resolver;
resolver.resolveNamesAndTypes(*ast.get());
return 0;
}

3
third/MainWin.cpp

@ -120,6 +120,7 @@ Main::Main(QWidget *parent) :
connect(ui->webView, &QWebView::loadFinished, [=]()
{
m_ethereum->poll();
m_whisper->poll();
});
connect(ui->webView, &QWebView::titleChanged, [=]()
@ -522,6 +523,8 @@ void Main::timerEvent(QTimerEvent*)
if (m_ethereum)
m_ethereum->poll();
if (m_whisper)
m_whisper->poll();
for (auto const& i: m_handlers)
if (ethereum()->checkWatch(i.first))

6
windows/LibEthereum.vcxproj

@ -69,10 +69,13 @@
</ClCompile>
<ClCompile Include="..\libdevcore\_libdevcore.cpp" />
<ClCompile Include="..\libdevcrypto\Common.cpp" />
<ClCompile Include="..\libdevcrypto\CryptoPP.cpp" />
<ClCompile Include="..\libdevcrypto\EC.cpp" />
<ClCompile Include="..\libdevcrypto\FileSystem.cpp" />
<ClCompile Include="..\libdevcrypto\MemoryDB.cpp" />
<ClCompile Include="..\libdevcrypto\OverlayDB.cpp" />
<ClCompile Include="..\libdevcrypto\SHA3.cpp" />
<ClCompile Include="..\libdevcrypto\SHA3MAC.cpp" />
<ClCompile Include="..\libdevcrypto\TrieCommon.cpp" />
<ClCompile Include="..\libdevcrypto\TrieDB.cpp" />
<ClCompile Include="..\libethcore\BlockInfo.cpp">
@ -270,10 +273,13 @@
<ClInclude Include="..\libdevcrypto\All.h" />
<ClInclude Include="..\libdevcrypto\Common.h" />
<ClInclude Include="..\libdevcrypto\CryptoHeaders.h" />
<ClInclude Include="..\libdevcrypto\CryptoPP.h" />
<ClInclude Include="..\libdevcrypto\EC.h" />
<ClInclude Include="..\libdevcrypto\FileSystem.h" />
<ClInclude Include="..\libdevcrypto\MemoryDB.h" />
<ClInclude Include="..\libdevcrypto\OverlayDB.h" />
<ClInclude Include="..\libdevcrypto\SHA3.h" />
<ClInclude Include="..\libdevcrypto\SHA3MAC.h" />
<ClInclude Include="..\libdevcrypto\TrieCommon.h" />
<ClInclude Include="..\libdevcrypto\TrieDB.h" />
<ClInclude Include="..\libethcore\All.h">

18
windows/LibEthereum.vcxproj.filters

@ -193,6 +193,15 @@
<ClCompile Include="..\libethcore\Exceptions.cpp">
<Filter>libethcore</Filter>
</ClCompile>
<ClCompile Include="..\libdevcrypto\CryptoPP.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
<ClCompile Include="..\libdevcrypto\EC.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
<ClCompile Include="..\libdevcrypto\SHA3MAC.cpp">
<Filter>libdevcrypto</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@ -417,6 +426,15 @@
<ClInclude Include="..\libwebthree\webthree.h">
<Filter>libwebthree</Filter>
</ClInclude>
<ClInclude Include="..\libdevcrypto\CryptoPP.h">
<Filter>libdevcrypto</Filter>
</ClInclude>
<ClInclude Include="..\libdevcrypto\EC.h">
<Filter>libdevcrypto</Filter>
</ClInclude>
<ClInclude Include="..\libdevcrypto\SHA3MAC.h">
<Filter>libdevcrypto</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Windows">

Loading…
Cancel
Save