Browse Source

GUI reboot.

Support for denominations in GUI.
Multi key wallet beginnings.
Transactional data beginnings.
GUI log.
Half-decent logging system.
cl-refactor
Gav Wood 11 years ago
parent
commit
1afda67310
  1. 592
      alethzero/Main.ui
  2. 177
      alethzero/MainWin.cpp
  3. 19
      alethzero/MainWin.h
  4. 5
      eth/main.cpp
  5. 5
      libethereum/Client.cpp
  6. 2
      libethereum/Client.h
  7. 85
      libethereum/Common.cpp
  8. 99
      libethereum/Common.h
  9. 178
      libethereum/PeerNetwork.cpp
  10. 20
      libethereum/PeerNetwork.h
  11. 2
      libethereum/State.cpp

592
alethzero/Main.ui

@ -1,198 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Main</class>
<widget class="QDialog" name="Main">
<widget class="QMainWindow" name="Main">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>991</width>
<height>556</height>
<width>1112</width>
<height>766</height>
</rect>
</property>
<property name="windowTitle">
<string>AlethZero Ethereum Client</string>
</property>
<property name="sizeGripEnabled">
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks|QMainWindow::VerticalTabs</set>
</property>
<property name="sizeGripEnabled" stdset="0">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="upnp">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>UPnP</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="net">
<property name="text">
<string>Net</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="port">
<property name="minimum">
<number>1024</number>
</property>
<property name="maximum">
<number>32767</number>
</property>
<property name="value">
<number>30303</number>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="connect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="value">
<property name="suffix">
<string> wei</string>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="fee">
<property name="suffix">
<string>)</string>
</property>
<property name="prefix">
<string>(fee </string>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="destination"/>
</item>
<item>
<widget class="QToolButton" name="send">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="create">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="mineProgress" native="true"/>
</item>
<item>
<widget class="QToolButton" name="mine">
<property name="text">
<string>Mine</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="peers"/>
<widget class="QListWidget" name="accounts">
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>4</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="transactions">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QListWidget" name="transactionQueue"/>
<widget class="QListWidget" name="transactions"/>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<number>0</number>
</property>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="balance">
<property name="text">
@ -201,9 +44,9 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="address">
<property name="readOnly">
<bool>true</bool>
<widget class="QLabel" name="peerCount">
<property name="text">
<string>0 peers</string>
</property>
</widget>
</item>
@ -214,17 +57,386 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="peerCount">
<property name="text">
<string>0 peers</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1112</width>
<height>28</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="quit"/>
</widget>
<widget class="QMenu" name="menu_Network">
<property name="title">
<string>&amp;Network</string>
</property>
<addaction name="upnp"/>
<addaction name="net"/>
<addaction name="connect"/>
</widget>
<widget class="QMenu" name="menu_Tools">
<property name="title">
<string>&amp;Tools</string>
</property>
<addaction name="mine"/>
<addaction name="create"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Network"/>
<addaction name="menu_Tools"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_2">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>All Accounts</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="accounts">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_3">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Network</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="peers">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Listen on</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="port">
<property name="minimum">
<number>1024</number>
</property>
<property name="maximum">
<number>32767</number>
</property>
<property name="value">
<number>30303</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_4">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_4">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="log">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Pending</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="transactionQueue">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="connect"/>
<addaction name="mine"/>
</widget>
<widget class="QDockWidget" name="dockWidget_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>349</width>
<height>225</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Transact</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="0" column="2" colspan="3">
<widget class="QLineEdit" name="destination">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="send">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item row="2" column="3" colspan="2">
<widget class="QComboBox" name="feeUnits"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>Amount</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="fee">
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label5_3">
<property name="text">
<string>Fee</string>
</property>
</widget>
</item>
<item row="3" column="2" colspan="3">
<widget class="QPlainTextEdit" name="data"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Data</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_7">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Owned Accounts</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_7">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="ourAccounts">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="quit">
<property name="text">
<string>&amp;Quit</string>
</property>
</action>
<action name="upnp">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Use &amp;UPnP</string>
</property>
</action>
<action name="connect">
<property name="text">
<string>&amp;Connect</string>
</property>
</action>
<action name="net">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Listen</string>
</property>
</action>
<action name="mine">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Mine</string>
</property>
</action>
<action name="create">
<property name="text">
<string>&amp;New Address</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>

177
alethzero/MainWin.cpp

@ -7,13 +7,22 @@
using namespace std;
using namespace eth;
static void initUnits(QComboBox* _b)
{
for (int n = units().size() - 1; n >= 0; --n)
_b->addItem(QString::fromStdString(units()[n].second), n);
_b->setCurrentIndex(6);
}
Main::Main(QWidget *parent) :
QDialog(parent),
QMainWindow(parent),
ui(new Ui::Main),
m_client("AlethZero/v0.1")
m_client("AlethZero/v0.1.1")
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
initUnits(ui->valueUnits);
initUnits(ui->feeUnits);
readSettings();
refresh();
@ -34,10 +43,13 @@ Main::Main(QWidget *parent) :
m_webCtrl.get(r);
srand(time(0));
#endif
g_logPost = [=](std::string const& s, char const*) { ui->log->addItem(QString::fromStdString(s)); };
}
Main::~Main()
{
g_logPost = simpleDebugOut;
writeSettings();
delete ui;
}
@ -46,8 +58,13 @@ void Main::writeSettings()
{
QSettings s("ethereum", "alethzero");
QByteArray b;
b.resize(32);
memcpy(b.data(), &m_myKey, 32);
b.resize(sizeof(Secret) * m_myKeys.size());
auto p = b.data();
for (auto i: m_myKeys)
{
memcpy(p, &(i.secret()), sizeof(Secret));
p += sizeof(Secret);
}
s.setValue("address", b);
// TODO: save peers - implement it in PeerNetwork though returning RLP bytes
@ -62,14 +79,17 @@ void Main::readSettings()
QSettings s("ethereum", "alethzero");
QByteArray b = s.value("address").toByteArray();
if (b.isEmpty())
m_myKey = KeyPair::create();
m_myKeys.append(KeyPair::create());
else
{
h256 k;
memcpy(&k, b.data(), 32);
m_myKey = KeyPair(k);
for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i)
{
memcpy(&k, b.data() + i * sizeof(Secret), sizeof(Secret));
m_myKeys.append(KeyPair(k));
}
}
m_client.setAddress(m_myKey.address());
m_client.setAddress(m_myKeys.back().address());
writeSettings();
@ -83,68 +103,89 @@ void Main::readSettings()
void Main::refresh()
{
m_client.lock();
ui->balance->setText(QString::fromStdString(formatBalance(m_client.state().balance(m_myKey.address()))));
ui->peerCount->setText(QString::fromStdString(toString(m_client.peerCount())) + " peer(s)");
ui->address->setText(QString::fromStdString(asHex(m_client.state().address().asArray())));
ui->peers->clear();
for (PeerInfo const& i: m_client.peers())
ui->peers->addItem(QString("%3 ms - %1:%2 - %4").arg(i.host.c_str()).arg(i.port).arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count()).arg(i.clientVersion.c_str()));
auto d = m_client.blockChain().details();
auto diff = BlockInfo(m_client.blockChain().block()).difficulty;
ui->blockChain->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
auto acs = m_client.state().addresses();
ui->accounts->clear();
for (auto i: acs)
ui->accounts->addItem(QString("%1 @ %2").arg(formatBalance(i.second).c_str()).arg(asHex(i.first.asArray()).c_str()));
ui->transactionQueue->clear();
for (pair<h256, bytes> const& i: m_client.transactionQueue().transactions())
if (m_client.changed())
{
Transaction t(i.second);
ui->transactionQueue->addItem(QString("%1 (%2 fee) @ %3 <- %4")
.arg(formatBalance(t.value).c_str())
.arg(formatBalance(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
}
ui->peerCount->setText(QString::fromStdString(toString(m_client.peerCount())) + " peer(s)");
ui->peers->clear();
for (PeerInfo const& i: m_client.peers())
ui->peers->addItem(QString("%3 ms - %1:%2 - %4").arg(i.host.c_str()).arg(i.port).arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count()).arg(i.clientVersion.c_str()));
auto d = m_client.blockChain().details();
auto diff = BlockInfo(m_client.blockChain().block()).difficulty;
ui->blockChain->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
auto acs = m_client.state().addresses();
ui->accounts->clear();
for (auto i: acs)
ui->accounts->addItem(QString("%1 @ %2").arg(formatBalance(i.second).c_str()).arg(asHex(i.first.asArray()).c_str()));
ui->transactionQueue->clear();
for (pair<h256, bytes> const& i: m_client.transactionQueue().transactions())
{
Transaction t(i.second);
ui->transactionQueue->addItem(QString("%1 (%2 fee) @ %3 <- %4")
.arg(formatBalance(t.value).c_str())
.arg(formatBalance(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
}
ui->transactions->clear();
auto const& bc = m_client.blockChain();
for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent)
{
auto d = bc.details(h);
ui->transactions->addItem(QString("# %1 ==== %2").arg(d.number).arg(asHex(h.asArray()).c_str()));
for (auto const& i: RLP(bc.block(h))[1])
ui->transactions->clear();
auto const& bc = m_client.blockChain();
for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent)
{
Transaction t(i.data());
ui->transactions->addItem(QString("%1 wei (%2 fee) @ %3 <- %4")
.arg(toString(t.value).c_str())
.arg(toString(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
auto d = bc.details(h);
ui->transactions->addItem(QString("# %1 ==== %2").arg(d.number).arg(asHex(h.asArray()).c_str()));
for (auto const& i: RLP(bc.block(h))[1])
{
Transaction t(i.data());
ui->transactions->addItem(QString("%1 (%2) @ %3 <- %4")
.arg(formatBalance(t.value).c_str())
.arg(formatBalance(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
}
}
}
ui->ourAccounts->clear();
u256 totalBalance = 0;
for (auto i: m_myKeys)
{
u256 b = m_client.state().balance(i.address());
ui->ourAccounts->addItem(QString("%1 @ %2").arg(formatBalance(b).c_str()).arg(asHex(i.address().asArray()).c_str()));
totalBalance += b;
}
ui->balance->setText(QString::fromStdString(formatBalance(totalBalance)));
m_client.unlock();
}
void Main::on_net_toggled()
void Main::on_ourAccounts_doubleClicked()
{
qApp->clipboard()->setText(ui->ourAccounts->currentItem()->text().section(" @ ", 1));
}
void Main::on_accounts_doubleClicked()
{
qApp->clipboard()->setText(ui->accounts->currentItem()->text().section(" @ ", 1));
}
void Main::on_net_triggered()
{
ui->port->setEnabled(!ui->net->isChecked());
if (ui->net->isChecked())
m_client.startNetwork(ui->port->value(), string(), 30303, 6, NodeMode::Full, 5, std::string(), ui->upnp->isChecked());
m_client.startNetwork(ui->port->value(), string(), 0, NodeMode::Full, 5, std::string(), ui->upnp->isChecked());
else
m_client.stopNetwork();
}
void Main::on_connect_clicked()
void Main::on_connect_triggered()
{
if (!ui->net->isChecked())
ui->net->setChecked(true);
bool ok = false;
QString s = QInputDialog::getItem(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", m_servers, m_servers.count() ? rand() % m_servers.count() : 0, true, &ok);
if (ok)
if (ok && s.contains(":"))
{
string host = s.section(":", 0, 0).toStdString();
short port = s.section(":", 1).toInt();
@ -152,25 +193,43 @@ void Main::on_connect_clicked()
}
}
void Main::on_mine_toggled()
void Main::on_mine_triggered()
{
if (ui->mine->isChecked())
{
m_client.setAddress(m_myKeys.last().address());
m_client.startMining();
}
else
m_client.stopMining();
}
void Main::on_send_clicked()
{
Secret s = m_myKey.secret();
Address r = Address(fromUserHex(ui->destination->text().toStdString()));
m_client.transact(s, r, ui->value->value(), ui->fee->value());
refresh();
u256 value = ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first;
u256 fee = ui->fee->value() * units()[units().size() - 1 - ui->feeUnits->currentIndex()].first;
u256 totalReq = value + fee;
m_client.lock();
for (auto i: m_myKeys)
if (m_client.state().balance(i.address()) >= totalReq)
{
m_client.unlock();
Secret s = m_myKeys.front().secret();
Address r = Address(fromUserHex(ui->destination->text().toStdString()));
auto ds = ui->data->toPlainText().split(QRegExp("[^0-9a-fA-Fx]+"));
u256s data;
data.reserve(ds.size());
for (QString const& i: ds)
data.push_back(u256(i.toStdString()));
m_client.transact(s, r, value, fee, data);
refresh();
return;
}
m_client.unlock();
statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount.");
}
void Main::on_create_clicked()
void Main::on_create_triggered()
{
KeyPair p = KeyPair::create();
QString s = QString::fromStdString("The new secret key is:\n" + asHex(p.secret().asArray()) + "\n\nAddress:\n" + asHex(p.address().asArray()));
QMessageBox::information(this, "Create Key", s, QMessageBox::Ok);
m_myKeys.append(KeyPair::create());
}

19
alethzero/MainWin.h

@ -3,7 +3,7 @@
#include <QtNetwork/QNetworkAccessManager>
#include <QAbstractListModel>
#include <QDialog>
#include <QMainWindow>
#include <QMutex>
#include <libethereum/Client.h>
@ -11,7 +11,7 @@ namespace Ui {
class Main;
}
class Main : public QDialog
class Main : public QMainWindow
{
Q_OBJECT
@ -20,11 +20,14 @@ public:
~Main();
private slots:
void on_connect_clicked();
void on_mine_toggled();
void on_connect_triggered();
void on_mine_triggered();
void on_send_clicked();
void on_create_clicked();
void on_net_toggled();
void on_create_triggered();
void on_net_triggered();
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_quit_triggered() { close(); }
void refresh();
@ -36,12 +39,10 @@ private:
eth::Client m_client;
eth::KeyPair m_myKey;
std::vector<bi::tcp::endpoint> m_peers;
QMutex m_guiLock;
QTimer* m_refresh;
QStringList m_servers;
QVector<eth::KeyPair> m_myKeys;
QNetworkAccessManager m_webCtrl;
};

5
eth/main.cpp

@ -68,7 +68,6 @@ int main(int argc, char** argv)
bool interactive = false;
string dbPath;
eth::uint mining = ~(eth::uint)0;
unsigned verbosity = 1;
NodeMode mode = NodeMode::Full;
unsigned peers = 5;
string publicIP;
@ -144,7 +143,7 @@ int main(int argc, char** argv)
}
}
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
verbosity = atoi(argv[++i]);
g_logVerbosity = atoi(argv[++i]);
else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
peers = atoi(argv[++i]);
else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
@ -229,7 +228,7 @@ int main(int argc, char** argv)
}
else
{
c.startNetwork(listenPort, remoteHost, remotePort, verbosity, mode, peers, publicIP, upnp);
c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp);
eth::uint n = c.blockChain().details().number;
while (true)
{

5
libethereum/Client.cpp

@ -41,7 +41,7 @@ Client::Client(std::string const& _clientVersion, Address _us, std::string const
m_s.sync(m_tq);
m_changed = true;
m_work = new thread([&](){ while (m_workState != Deleting) work(); m_workState = Deleted; });
m_work = new thread([&](){ setThreadName("eth"); while (m_workState != Deleting) work(); m_workState = Deleted; });
}
Client::~Client()
@ -52,13 +52,12 @@ Client::~Client()
usleep(10000);
}
void Client::startNetwork(short _listenPort, std::string const& _seedHost, short _port, unsigned _verbosity, NodeMode _mode, unsigned _peers, string const& _publicIP, bool _upnp)
void Client::startNetwork(short _listenPort, std::string const& _seedHost, short _port, NodeMode _mode, unsigned _peers, string const& _publicIP, bool _upnp)
{
if (m_net)
return;
m_net = new PeerServer(m_clientVersion, m_bc, 0, _listenPort, _mode, _publicIP, _upnp);
m_net->setIdealPeerCount(_peers);
m_net->setVerbosity(_verbosity);
if (_seedHost.size())
m_net->connect(_seedHost, _port);
}

2
libethereum/Client.h

@ -92,7 +92,7 @@ public:
unsigned peerCount() const { return m_net ? m_net->peerCount() : 0; }
/// Start the network subsystem.
void startNetwork(short _listenPort = 30303, std::string const& _seedHost = std::string(), short _port = 30303, unsigned _verbosity = 4, NodeMode _mode = NodeMode::Full, unsigned _peers = 5, std::string const& _publicIP = std::string(), bool _upnp = true);
void startNetwork(short _listenPort = 30303, std::string const& _seedHost = std::string(), short _port = 30303, NodeMode _mode = NodeMode::Full, unsigned _peers = 5, std::string const& _publicIP = std::string(), bool _upnp = true);
/// Connect to a particular peer.
void connect(std::string const& _seedHost, short _port = 30303);
/// Stop the network subsystem.

85
libethereum/Common.cpp

@ -18,6 +18,10 @@
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "Common.h"
#include <random>
#if WIN32
#pragma warning(push)
#pragma warning(disable:4244)
@ -30,32 +34,22 @@
#pragma warning(pop)
#else
#endif
#include <random>
#include "Common.h"
#include "Exceptions.h"
using namespace std;
using namespace eth;
// Logging
bool eth::g_debugEnabled[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, true, true, true, true, true};
char const* g_debugName[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ">>>", "<<<", "LOG", "---", "***", "!!!"};
int eth::g_logVerbosity = 6;
map<type_info const*, bool> eth::g_logOverride;
thread_local std::string eth::t_logThreadName = "???";
static std::string g_mainThreadName = (eth::t_logThreadName = "main");
void eth::simpleDebugOut(std::string const& _s, unsigned char _id)
void eth::simpleDebugOut(std::string const& _s, char const*)
{
// TODO: Time & thread.
if (g_debugEnabled[_id])
std::cout << (g_debugName[_id] ? g_debugName[_id] : " ") << " " << _s << std::endl << std::flush;
cout << _s << endl << flush;
}
std::function<void(std::string const&, unsigned char)> eth::g_debugPost = simpleDebugOut;
std::function<void(char, std::string const&)> eth::g_syslogPost =
[](char _c, string const& _s)
{
if (_c == 'C')
simpleDebugOut(_s, LogChannel);
else
simpleDebugOut("<binary>", LogChannel);
};
std::function<void(std::string const&, char const*)> eth::g_logPost = simpleDebugOut;
std::string eth::escaped(std::string const& _s, bool _all)
{
@ -202,38 +196,45 @@ KeyPair KeyPair::create()
return ret;
}
static const vector<pair<u256, string>> g_units =
{
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Uether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Vether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Dether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Nether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Yether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Zether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000000, "Eether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000, "Pether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000, "Tether"},
{(u256(1000000000) * 1000000000) * 1000000000, "Gether"},
{(u256(1000000000) * 1000000000) * 1000000, "Mether"},
{(u256(1000000000) * 1000000000) * 1000, "Kether"},
{u256(1000000000) * 1000000000, "ether"},
{u256(1000000000) * 1000000, "finney"},
{u256(1000000000) * 1000, "szabo"},
{u256(1000000000), "Gwei"},
{u256(1000000), "Mwei"},
{u256(1000), "Kwei"},
{u256(1), "wei"}
};
vector<pair<u256, string>> const& eth::units()
{
return g_units;
}
std::string eth::formatBalance(u256 _b)
{
static const vector<pair<u256, string>> c_units =
{
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Uether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Vether"},
{((((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Dether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000000, "Nether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000000, "Yether"},
{(((u256(1000000000) * 1000000000) * 1000000000) * 1000000000) * 1000, "Zether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000000, "Eether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000000, "Pether"},
{((u256(1000000000) * 1000000000) * 1000000000) * 1000, "Tether"},
{(u256(1000000000) * 1000000000) * 1000000000, "Gether"},
{(u256(1000000000) * 1000000000) * 1000000, "Mether"},
{(u256(1000000000) * 1000000000) * 1000, "Kether"},
{u256(1000000000) * 1000000000, "ether"},
{u256(1000000000) * 1000000, "finney"},
{u256(1000000000) * 1000, "szabo"},
{u256(1000000000), "Gwei"},
{u256(1000000), "Mwei"},
{u256(1000), "Kwei"}
};
ostringstream ret;
if (_b > c_units[0].first * 10000)
if (_b > g_units[0].first * 10000)
{
ret << (_b / c_units[0].first) << " " << c_units[0].second;
ret << (_b / g_units[0].first) << " " << g_units[0].second;
return ret.str();
}
ret << setprecision(5);
for (auto const& i: c_units)
if (_b >= i.first * 100)
for (auto const& i: g_units)
if (i.first != 1 && _b >= i.first * 100)
{
ret << (double(_b / (i.first / 1000)) / 1000.0) << " " << i.second;
return ret.str();

99
libethereum/Common.h

@ -28,6 +28,9 @@
#pragma warning(disable:4244)
#endif
#include <ctime>
#include <iomanip>
#include <chrono>
#include <array>
#include <map>
#include <set>
@ -148,68 +151,63 @@ public:
template <class T> NullOutputStream& operator<<(T const&) { return *this; }
};
extern bool g_debugEnabled[256];
static const uint8_t WarnChannel = 255;
static const uint8_t NoteChannel = 254;
static const uint8_t DebugChannel = 253;
static const uint8_t LogChannel = 252;
static const uint8_t LeftChannel = 251;
static const uint8_t RightChannel = 250;
// Unused for now.
/*template <uint8_t _Channel> struct LogName { static const char constexpr* name = " "; };
template <> struct LogName<LeftChannel> { static const char constexpr* name = "<<<"; };
template <> struct LogName<RightChannel> { static const char constexpr* name = ">>>"; };
template <> struct LogName<WarnChannel> { static const char constexpr* name = "!!!"; };
template <> struct LogName<NoteChannel> { static const char constexpr* name = "***"; };
template <> struct LogName<DebugChannel> { static const char constexpr* name = "---"; };
template <> struct LogName<LogChannel> { static const char constexpr* name = "LOG"; };*/
extern std::function<void(std::string const&, unsigned char)> g_debugPost;
extern std::function<void(char, std::string const&)> g_syslogPost;
void simpleDebugOut(std::string const&, unsigned char);
template <unsigned char _Id = 0, bool _AutoSpacing = true>
class DebugOutputStream
{
public:
DebugOutputStream(char const* _start = " ") { sstr << _start; }
~DebugOutputStream() { g_debugPost(sstr.str(), _Id); }
template <class T> DebugOutputStream& operator<<(T const& _t) { if (_AutoSpacing && sstr.str().size() && sstr.str().back() != ' ') sstr << " "; sstr << _t; return *this; }
std::stringstream sstr;
};
extern std::map<std::type_info const*, bool> g_logOverride;
extern thread_local std::string t_logThreadName;
inline void setThreadName(std::string const& _n) { t_logThreadName = _n; }
struct LogChannel { static const char constexpr* name = " "; static const int verbosity = 1; };
struct LeftChannel: public LogChannel { static const char constexpr* name = "<<<"; };
struct RightChannel: public LogChannel { static const char constexpr* name = ">>>"; };
struct WarnChannel: public LogChannel { static const char constexpr* name = "!!!"; static const int verbosity = 0; };
struct NoteChannel: public LogChannel { static const char constexpr* name = "***"; };
struct DebugChannel: public LogChannel { static const char constexpr* name = "---"; static const int verbosity = 0; };
template <bool _AutoSpacing = true>
class SysLogOutputStream
extern int g_logVerbosity;
extern std::function<void(std::string const&, char const*)> g_logPost;
void simpleDebugOut(std::string const&, char const* );
template <class Id, bool _AutoSpacing = true>
class LogOutputStream
{
public:
SysLogOutputStream() {}
~SysLogOutputStream() { if (sstr.str().size()) g_syslogPost('C', sstr.str()); }
template <class T> SysLogOutputStream& operator<<(T const& _t) { if (_AutoSpacing && sstr.str().size() && sstr.str().back() != ' ') sstr << " "; sstr << _t; return *this; }
static void write(char _type, std::string const& _s) { g_syslogPost(_type, _s); }
template <class _T> static void writePod(char _type, _T const& _s) { char const* begin = (char const*)&_s; char const* end = (char const*)&_s + sizeof(_T); g_syslogPost(_type, std::string(begin, end)); }
LogOutputStream(bool _term = true)
{
std::type_info const* i = &typeid(Id);
auto it = g_logOverride.find(i);
if ((it != g_logOverride.end() && it->second == true) || (it == g_logOverride.end() && Id::verbosity <= g_logVerbosity))
{
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
sstr << Id::name << " [ " << rawTime /*put_time("%T", std::localtime(&rawTime)) */<< " | " << t_logThreadName << (_term ? " ] " : "");
}
}
~LogOutputStream() { if (Id::verbosity <= g_logVerbosity) g_logPost(sstr.str(), Id::name); }
template <class T> LogOutputStream& operator<<(T const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && sstr.str().size() && sstr.str().back() != ' ') sstr << " "; sstr << _t; } return *this; }
std::stringstream sstr;
};
// Dirties the global namespace, but oh so convenient...
#define cnote eth::DebugOutputStream<eth::NoteChannel, true>()
#define cwarn eth::DebugOutputStream<eth::WarnChannel, true>()
#define cnote eth::LogOutputStream<eth::NoteChannel, true>()
#define cwarn eth::LogOutputStream<eth::WarnChannel, true>()
#define nbug(X) if (true) {} else eth::NullOutputStream()
#define nsbug(X) if (true) {} else eth::NullOutputStream()
#define ndebug if (true) {} else eth::NullOutputStream()
#define nlog(X) if (true) {} else eth::NullOutputStream()
#define nslog(X) if (true) {} else eth::NullOutputStream()
#if NDEBUG
#define cbug(X) nbug(X)
#define csbug(X) nsbug(X)
#define cdebug ndebug
#else
#define cbug(X) eth::DebugOutputStream<X>()
#define csbug(X) eth::DebugOutputStream<X, false>()
#define cdebug eth::DebugOutputStream<eth::DebugChannel, true>()
#define cdebug eth::LogOutputStream<eth::DebugChannel, true>()
#endif
#define clog eth::SysLogOutputStream<true>()
#if NLOG
#define clog(X) nlog(X)
#define cslog(X) nslog(X)
#else
#define clog(X) eth::LogOutputStream<X, true>()
#define cslog(X) eth::LogOutputStream<X, false>()
#endif
@ -412,6 +410,9 @@ h256 sha3(bytesConstRef _input);
inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_input)); }
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
/// Get information concerning the currency denominations.
std::vector<std::pair<u256, std::string>> const& units();
/// Convert a private key into the public key equivalent.
/// @returns 0 if it's not a valid private key.
Address toAddress(h256 _private);
@ -424,8 +425,8 @@ public:
static KeyPair create();
Secret secret() const { return m_secret; }
Address address() const { return m_address; }
Secret const& secret() const { return m_secret; }
Address const& address() const { return m_address; }
private:
Secret m_secret;

178
libethereum/PeerNetwork.cpp

@ -40,6 +40,8 @@
using namespace std;
using namespace eth;
#define clogS(X) eth::LogOutputStream<X, true>(false) << " | " << std::setw(2) << m_socket.native_handle() << " ] "
static const eth::uint c_maxHashes = 256; ///< Maximum number of hashes GetChain will ever send.
static const eth::uint c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send. BUG: if this gets too big (e.g. 2048) stuff starts going wrong.
static const eth::uint c_maxBlocksAsk = 2048; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
@ -84,8 +86,7 @@ bi::tcp::endpoint PeerSession::endpoint() const
bool PeerSession::interpret(RLP const& _r)
{
if (m_server->m_verbosity >= 8)
cout << ">>> " << _r << endl;
clogS(NetRight) << _r;
switch (_r[0].toInt<unsigned>())
{
case HelloPacket:
@ -96,10 +97,9 @@ bool PeerSession::interpret(RLP const& _r)
m_caps = _r.itemCount() > 4 ? _r[4].toInt<uint>() : 0x07;
m_listenPort = _r.itemCount() > 5 ? _r[5].toInt<short>() : 0;
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | Hello: " << clientVersion << " " << showbase << hex << m_caps << dec << " " << m_listenPort << endl;
clogS(NetMessageSummary) << "Hello: " << clientVersion << " " << showbase << hex << m_caps << dec << " " << m_listenPort;
if (m_protocolVersion != 0 || m_networkId != m_reqNetworkId)
if (m_protocolVersion != 1 || m_networkId != m_reqNetworkId)
{
disconnect();
return false;
@ -131,53 +131,45 @@ bool PeerSession::interpret(RLP const& _r)
break;
}
case DisconnectPacket:
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | Disconnect" << endl;
if (m_server->m_verbosity >= 1)
{
if (m_socket.is_open())
cout << "Closing " << m_socket.remote_endpoint() << endl;
else
cout << "Remote closed on " << m_socket.native_handle() << endl;
}
clogS(NetMessageSummary) << "Disconnect";
if (m_socket.is_open())
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
else
clogS(NetNote) << "Remote closed.";
m_socket.close();
return false;
case PingPacket:
{
// cout << std::setw(2) << m_socket.native_handle() << " | Ping" << endl;
// clogS(NetMessageSummary) << "Ping";
RLPStream s;
sealAndSend(prep(s).appendList(1) << PongPacket);
break;
}
case PongPacket:
m_info.lastPing = std::chrono::steady_clock::now() - m_ping;
// cout << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_lastPing).count() << " ms" << endl;
// clogS(NetMessageSummary) << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_lastPing).count() << " ms";
break;
case GetPeersPacket:
{
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | GetPeers" << endl;
clogS(NetMessageSummary) << "GetPeers";
std::vector<bi::tcp::endpoint> peers = m_server->potentialPeers();
RLPStream s;
prep(s).appendList(peers.size() + 1);
s << PeersPacket;
for (auto i: peers)
{
if (m_server->m_verbosity >= 3)
cout << " Sending peer " << i << endl;
clogS(NetMessageDetail) << "Sending peer " << i;
s.appendList(2) << i.address().to_v4().to_bytes() << i.port();
}
sealAndSend(s);
break;
}
case PeersPacket:
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | Peers (" << dec << (_r.itemCount() - 1) << " entries)" << endl;
clogS(NetMessageSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto ep = bi::tcp::endpoint(bi::address_v4(_r[i][0].toArray<byte, 4>()), _r[i][1].toInt<short>());
if (m_server->m_verbosity >= 6)
cout << "Checking: " << ep << endl;
clogS(NetAllDetail) << "Checking: " << ep;
// check that we're not already connected to addr:
if (!ep.port())
goto CONTINUE;
@ -187,8 +179,7 @@ bool PeerSession::interpret(RLP const& _r)
for (auto i: m_server->m_peers)
if (shared_ptr<PeerSession> p = i.lock())
{
if (m_server->m_verbosity >= 6)
cout << " ...against " << p->endpoint() << endl;
clogS(NetAllDetail) << " ...against " << p->endpoint();
if (p->m_socket.is_open() && p->endpoint() == ep)
goto CONTINUE;
}
@ -196,16 +187,14 @@ bool PeerSession::interpret(RLP const& _r)
if (i == ep)
goto CONTINUE;
m_server->m_incomingPeers.push_back(ep);
if (m_server->m_verbosity >= 3)
cout << "New peer: " << ep << endl;
clogS(NetMessageDetail) << "New peer: " << ep;
CONTINUE:;
}
break;
case TransactionsPacket:
if (m_server->m_mode == NodeMode::PeerServer)
break;
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | Transactions (" << dec << (_r.itemCount() - 1) << " entries)" << endl;
clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << " entries)";
m_rating += _r.itemCount() - 1;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
@ -216,23 +205,22 @@ bool PeerSession::interpret(RLP const& _r)
case BlocksPacket:
if (m_server->m_mode == NodeMode::PeerServer)
break;
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | Blocks (" << dec << (_r.itemCount() - 1) << " entries)" << endl;
clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << " entries)";
m_rating += _r.itemCount() - 1;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
m_server->m_incomingBlocks.push_back(_r[i].data().toBytes());
m_knownBlocks.insert(sha3(_r[i].data()));
}
if (m_server->m_verbosity >= 3)
if (g_logVerbosity >= 3)
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto h = sha3(_r[i].data());
BlockInfo bi(_r[i].data());
if (!m_server->m_chain->details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash))
cerr << "*** Unknown parent " << bi.parentHash << " of block " << h << endl;
clogS(NetMessageDetail) << "Unknown parent " << bi.parentHash << " of block " << h;
else
cerr << "--- Known parent " << bi.parentHash << " of block " << h << endl;
clogS(NetMessageDetail) << "Known parent " << bi.parentHash << " of block " << h;
}
if (_r.itemCount() > 1) // we received some - check if there's any more
{
@ -254,14 +242,12 @@ bool PeerSession::interpret(RLP const& _r)
parents.reserve(_r.itemCount() - 2);
for (unsigned i = 1; i < _r.itemCount() - 1; ++i)
parents.push_back(_r[i].toHash<h256>());
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | GetChain (" << (_r.itemCount() - 2) << " hashes, " << (_r[_r.itemCount() - 1].toInt<bigint>()) << ")" << endl;
clogS(NetMessageSummary) << "GetChain (" << (_r.itemCount() - 2) << " hashes, " << (_r[_r.itemCount() - 1].toInt<bigint>()) << ")";
if (_r.itemCount() == 2)
break;
// return 2048 block max.
uint baseCount = (uint)min<bigint>(_r[_r.itemCount() - 1].toInt<bigint>(), c_maxBlocks);
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | GetChain (" << baseCount << " max, from " << parents.front() << " to " << parents.back() << ")" << endl;
clogS(NetMessageSummary) << "GetChain (" << baseCount << " max, from " << parents.front() << " to " << parents.back() << ")";
for (auto parent: parents)
{
auto h = m_server->m_chain->currentHash();
@ -275,27 +261,23 @@ bool PeerSession::interpret(RLP const& _r)
latestNumber = m_server->m_chain->details(latest).number;
parentNumber = m_server->m_chain->details(parent).number;
uint count = min<uint>(latestNumber - parentNumber, baseCount);
if (m_server->m_verbosity >= 6)
cout << "Requires " << dec << (latestNumber - parentNumber) << " blocks from " << latestNumber << " to " << parentNumber << endl
<< latest << " - " << parent << endl;
clogS(NetAllDetail) << "Requires " << dec << (latestNumber - parentNumber) << " blocks from " << latestNumber << " to " << parentNumber;
clogS(NetAllDetail) << latest << " - " << parent;
prep(s);
s.appendList(1 + count) << BlocksPacket;
uint endNumber = m_server->m_chain->details(parent).number;
uint startNumber = endNumber + count;
if (m_server->m_verbosity >= 6)
cout << "Sending " << dec << count << " blocks from " << startNumber << " to " << endNumber << endl;
clogS(NetAllDetail) << "Sending " << dec << count << " blocks from " << startNumber << " to " << endNumber;
uint n = latestNumber;
for (; n > startNumber; n--, h = m_server->m_chain->details(h).parent) {}
for (uint i = 0; h != parent && n > endNumber && i < count; ++i, --n, h = m_server->m_chain->details(h).parent)
{
if (m_server->m_verbosity >= 6)
cout << " " << dec << i << " " << h << endl;
clogS(NetAllDetail) << " " << dec << i << " " << h;
s.appendRaw(m_server->m_chain->block(h));
}
if (m_server->m_verbosity >= 6)
cout << "Parent: " << h << endl;
clogS(NetAllDetail) << "Parent: " << h;
}
else if (parent != parents.back())
continue;
@ -306,8 +288,7 @@ bool PeerSession::interpret(RLP const& _r)
if (parent == parents.back())
{
// out of parents...
if (m_server->m_verbosity >= 6)
cout << std::setw(2) << m_socket.native_handle() << " | GetChain failed; not in chain" << endl;
clogS(NetAllDetail) << "GetChain failed; not in chain";
// No good - must have been on a different branch.
s.clear();
prep(s).appendList(2) << NotInChainPacket << parents.back();
@ -328,12 +309,10 @@ bool PeerSession::interpret(RLP const& _r)
if (m_server->m_mode == NodeMode::PeerServer)
break;
h256 noGood = _r[1].toHash<h256>();
if (m_server->m_verbosity >= 2)
cout << std::setw(2) << m_socket.native_handle() << " | NotInChain (" << noGood << ")" << endl;
clogS(NetMessageSummary) << "NotInChain (" << noGood << ")";
if (noGood == m_server->m_chain->genesisHash())
{
if (m_server->m_verbosity)
cout << std::setw(2) << m_socket.native_handle() << " | Discordance over genesis block! Disconnect." << endl;
clogS(NetWarn) << "Discordance over genesis block! Disconnect.";
disconnect();
}
else
@ -377,8 +356,7 @@ RLPStream& PeerSession::prep(RLPStream& _s)
void PeerServer::seal(bytes& _b)
{
if (m_verbosity >= 9)
cbug(LeftChannel) << RLP(bytesConstRef(&_b).cropped(8));
clogS(NetLeft) << RLP(bytesConstRef(&_b).cropped(8));
_b[0] = 0x22;
_b[1] = 0x40;
_b[2] = 0x08;
@ -403,13 +381,11 @@ void PeerSession::sendDestroy(bytes& _msg)
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg);
assert((*buffer)[0] == 0x22);
// cout << "Sending " << (buffer->size() - 8) << endl;
// cout << "Sending " << RLP(bytesConstRef(buffer.get()).cropped(8)) << endl;
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
dropped();
// cout << length << " bytes written (EC: " << ec << ")" << endl;
// cbug << length << " bytes written (EC: " << ec << ")";
});
}
@ -417,24 +393,20 @@ void PeerSession::send(bytesConstRef _msg)
{
std::shared_ptr<bytes> buffer = std::make_shared<bytes>(_msg.toBytes());
assert((*buffer)[0] == 0x22);
// cout << "Sending " << (_msg.size() - 8) << endl;// RLP(bytesConstRef(buffer.get()).cropped(8)) << endl;
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
dropped();
// cout << length << " bytes written (EC: " << ec << ")" << endl;
// cbug << length << " bytes written (EC: " << ec << ")";
});
}
void PeerSession::dropped()
{
if (m_server->m_verbosity >= 1)
{
if (m_socket.is_open())
try {
cout << "Closing " << m_socket.remote_endpoint() << endl;
}catch (...){}
}
if (m_socket.is_open())
try {
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
}catch (...){}
m_socket.close();
for (auto i = m_server->m_peers.begin(); i != m_server->m_peers.end(); ++i)
if (i->lock().get() == this)
@ -458,15 +430,12 @@ void PeerSession::disconnect()
}
else
{
if (m_server->m_verbosity >= 1)
{
if (m_socket.is_open())
try {
cout << "Closing " << m_socket.remote_endpoint() << endl;
} catch (...){}
else
cout << "Remote closed on" << m_socket.native_handle() << endl;
}
if (m_socket.is_open())
try {
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
} catch (...){}
else
clogS(NetNote) << "Remote closed on" << m_socket.native_handle();
m_socket.close();
}
}
@ -503,15 +472,14 @@ void PeerSession::doRead()
{
if (m_incoming[0] != 0x22 || m_incoming[1] != 0x40 || m_incoming[2] != 0x08 || m_incoming[3] != 0x91)
{
if (m_server->m_verbosity)
cerr << std::setw(2) << m_socket.native_handle() << " | Out of alignment. Skipping: " << hex << showbase << (int)m_incoming[0] << dec << endl;
clogS(NetWarn) << "Out of alignment. Skipping: " << hex << showbase << (int)m_incoming[0] << dec;
memmove(m_incoming.data(), m_incoming.data() + 1, m_incoming.size() - 1);
m_incoming.resize(m_incoming.size() - 1);
}
else
{
uint32_t len = fromBigEndian<uint32_t>(bytesConstRef(m_incoming.data() + 4, 4));
// cout << "Received packet of " << len << " bytes" << endl;
// cdebug << "Received packet of " << len << " bytes";
if (m_incoming.size() - 8 < len)
break;
@ -528,8 +496,7 @@ void PeerSession::doRead()
}
catch (std::exception const& _e)
{
if (m_server->m_verbosity)
cerr << std::setw(2) << m_socket.native_handle() << " | ERROR: " << _e.what() << endl;
clogS(NetWarn) << "ERROR: " << _e.what();
dropped();
}
}
@ -548,8 +515,7 @@ PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch,
populateAddresses();
determinePublic(_publicAddress, _upnp);
ensureAccepting();
if (m_verbosity)
cout << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full") << endl;
clog(NetNote) << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full");
}
PeerServer::PeerServer(std::string const& _clientVersion, uint _networkId):
@ -561,8 +527,7 @@ PeerServer::PeerServer(std::string const& _clientVersion, uint _networkId):
{
// populate addresses.
populateAddresses();
if (m_verbosity)
cout << "Genesis: " << m_chain->genesisHash() << endl;
clog(NetNote) << "Genesis: " << m_chain->genesisHash();
}
PeerServer::~PeerServer()
@ -585,14 +550,14 @@ void PeerServer::determinePublic(string const& _publicAddress, bool _upnp)
bi::tcp::resolver r(m_ioService);
if (m_upnp && m_upnp->isValid() && m_peerAddresses.size())
{
cnote << "External addr: " << m_upnp->externalIP();
clog(NetNote) << "External addr: " << m_upnp->externalIP();
int p = m_upnp->addRedirect(m_peerAddresses[0].to_string().c_str(), m_listenPort);
if (p)
cnote << "Punched through NAT and mapped local port" << m_listenPort << "onto external port" << p << ".";
clog(NetNote) << "Punched through NAT and mapped local port" << m_listenPort << "onto external port" << p << ".";
else
{
// couldn't map
cwarn << "Couldn't punch through NAT (or no NAT in place). Assuming " << m_listenPort << " is local & external port.";
clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place). Assuming " << m_listenPort << " is local & external port.";
p = m_listenPort;
}
@ -625,7 +590,7 @@ void PeerServer::populateAddresses()
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
{
cerr << "Error " << WSAGetLastError() << " when getting local host name." << endl;
clog(NetWarn) << "Error " << WSAGetLastError() << " when getting local host name.";
WSACleanup();
throw NoNetworking();
}
@ -633,7 +598,7 @@ void PeerServer::populateAddresses()
struct hostent* phe = gethostbyname(ac);
if (phe == 0)
{
cerr << "Bad host lookup." << endl;
clog(NetWarn) << "Bad host lookup.";
WSACleanup();
throw NoNetworking();
}
@ -648,8 +613,7 @@ void PeerServer::populateAddresses()
bool isLocal = std::find(c_rejectAddresses.begin(), c_rejectAddresses.end(), ad) != c_rejectAddresses.end();
if (isLocal)
m_peerAddresses.push_back(ad.to_v4());
if (m_verbosity >= 1)
cout << "Address: " << ac << " = " << m_addresses.back() << (isLocal ? " [LOCAL]" : " [PEER]") << endl;
clog(NetNote) << "Address: " << ac << " = " << m_addresses.back() << (isLocal ? " [LOCAL]" : " [PEER]");
}
WSACleanup();
@ -676,8 +640,7 @@ void PeerServer::populateAddresses()
bool isLocal = std::find(c_rejectAddresses.begin(), c_rejectAddresses.end(), ad) != c_rejectAddresses.end();
if (!isLocal)
m_peerAddresses.push_back(ad.to_v4());
if (m_verbosity >= 1)
cout << "Address: " << host << " = " << m_addresses.back() << (isLocal ? " [LOCAL]" : " [PEER]") << endl;
clog(NetNote) << "Address: " << host << " = " << m_addresses.back() << (isLocal ? " [LOCAL]" : " [PEER]");
}
}
@ -704,26 +667,23 @@ void PeerServer::ensureAccepting()
{
if (m_accepting == false)
{
if (m_verbosity >= 1)
cout << "Listening on local port " << m_listenPort << " (public: " << m_public << ")" << endl;
clog(NetNote) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")";
m_accepting = true;
m_acceptor.async_accept(m_socket, [=](boost::system::error_code ec)
{
if (!ec)
try
{
if (m_verbosity >= 1)
try {
cout << "Accepted connection from " << m_socket.remote_endpoint() << std::endl;
} catch (...){}
try {
clog(NetNote) << "Accepted connection from " << m_socket.remote_endpoint();
} catch (...){}
auto p = std::make_shared<PeerSession>(this, std::move(m_socket), m_requiredNetworkId);
m_peers.push_back(p);
p->start();
}
catch (std::exception const& _e)
{
if (m_verbosity)
cerr << "*** ERROR: " << _e.what() << endl;
clog(NetWarn) << "ERROR: " << _e.what();
}
m_accepting = false;
@ -735,22 +695,19 @@ void PeerServer::ensureAccepting()
void PeerServer::connect(bi::tcp::endpoint const& _ep)
{
if (m_verbosity >= 1)
cout << "Attempting connection to " << _ep << endl;
clog(NetNote) << "Attempting connection to " << _ep;
bi::tcp::socket* s = new bi::tcp::socket(m_ioService);
s->async_connect(_ep, [=](boost::system::error_code const& ec)
{
if (ec)
{
if (m_verbosity >= 1)
cout << "Connection refused to " << _ep << " (" << ec.message() << ")" << endl;
clog(NetNote) << "Connection refused to " << _ep << " (" << ec.message() << ")";
}
else
{
auto p = make_shared<PeerSession>(this, std::move(*s), m_requiredNetworkId);
m_peers.push_back(p);
if (m_verbosity >= 1)
cout << "Connected to " << p->endpoint() << endl;
clog(NetNote) << "Connected to " << p->endpoint();
p->start();
}
delete s;
@ -791,8 +748,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
{
// First time - just initialise.
m_latestBlockSent = _bc.currentHash();
if (m_verbosity)
cout << "Initialising: latest=" << m_latestBlockSent << endl;
clog(NetNote) << "Initialising: latest=" << m_latestBlockSent;
for (auto const& i: _tq.transactions())
m_transactionsSent.insert(i.first);

20
libethereum/PeerNetwork.h

@ -37,6 +37,14 @@ namespace eth
class BlockChain;
class TransactionQueue;
struct NetWarn: public LogChannel { static const char constexpr* name = "!N!"; static const int verbosity = 0; };
struct NetNote: public LogChannel { static const char constexpr* name = "*N*"; static const int verbosity = 1; };
struct NetMessageSummary: public LogChannel { static const char constexpr* name = "-N-"; static const int verbosity = 2; };
struct NetMessageDetail: public LogChannel { static const char constexpr* name = "=N="; static const int verbosity = 3; };
struct NetAllDetail: public LogChannel { static const char constexpr* name = "=N="; static const int verbosity = 6; };
struct NetRight: public LogChannel { static const char constexpr* name = ">N>"; static const int verbosity = 8; };
struct NetLeft: public LogChannel { static const char constexpr* name = "<N<"; static const int verbosity = 9; };
enum PacketType
{
HelloPacket = 0,
@ -144,7 +152,6 @@ public:
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
void setMode(NodeMode _m) { m_mode = _m; }
void setVerbosity(unsigned _i) { m_verbosity = _i; }
/// Get peer information.
std::vector<PeerInfo> peers() const;
@ -168,17 +175,6 @@ private:
std::string m_clientVersion;
NodeMode m_mode = NodeMode::Full;
/**
* 0: Quiet - just errors on stderr.
* 1: Accepting/connecting/connected & one-off info.
* 2: Messages summary.
* 3: Messages detail.
* 6: Debug details.
* 8: Received raw.
* 9: Sent raw.
*/
unsigned m_verbosity = 4;
short m_listenPort;
BlockChain const* m_chain = nullptr;

2
libethereum/State.cpp

@ -67,7 +67,7 @@ std::map<Address, AddressState> const& eth::genesisState()
if (s_ret.empty())
{
// Initialise.
s_ret[Address(fromUserHex("812413ae7e515a3bcaf7b3444116527bce958c02"))] = AddressState(u256(1) << 200, 0);
s_ret[Address(fromUserHex("07598a40bfaa73256b60764c1bf40675a99083ef"))] = AddressState(u256(1) << 200, 0);
s_ret[Address(fromUserHex("93658b04240e4bd4046fd2d6d417d20f146f4b43"))] = AddressState(u256(1) << 200, 0);
s_ret[Address(fromUserHex("1e12515ce3e0f817a4ddef9ca55788a1d66bd2df"))] = AddressState(u256(1) << 200, 0);
s_ret[Address(fromUserHex("80c01a26338f0d905e295fccb71fa9ea849ffa12"))] = AddressState(u256(1) << 200, 0);

Loading…
Cancel
Save